]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/tcpdump/print-llc.c
This commit was generated by cvs2svn to compensate for changes in r100490,
[FreeBSD/FreeBSD.git] / contrib / 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  * $FreeBSD$
25  */
26
27 #ifndef lint
28 static const char rcsid[] =
29     "@(#) $Header: /tcpdump/master/tcpdump/print-llc.c,v 1.43 2001/10/08 21:25:22 fenner Exp $";
30 #endif
31
32 #ifdef HAVE_CONFIG_H
33 #include "config.h"
34 #endif
35
36 #include <sys/param.h>
37 #include <sys/time.h>
38
39 #include <netinet/in.h>
40
41 #include <ctype.h>
42 #include <netdb.h>
43 #include <stdio.h>
44 #include <string.h>
45
46 #include "interface.h"
47 #include "addrtoname.h"
48 #include "extract.h"                    /* must come after interface.h */
49
50 #include "llc.h"
51 #include "ethertype.h"
52
53 static struct tok cmd2str[] = {
54         { LLC_UI,       "ui" },
55         { LLC_TEST,     "test" },
56         { LLC_XID,      "xid" },
57         { LLC_UA,       "ua" },
58         { LLC_DISC,     "disc" },
59         { LLC_DM,       "dm" },
60         { LLC_SABME,    "sabme" },
61         { LLC_FRMR,     "frmr" },
62         { 0,            NULL }
63 };
64
65 /*
66  * Returns non-zero IFF it succeeds in printing the header
67  */
68 int
69 llc_print(const u_char *p, u_int length, u_int caplen,
70           const u_char *esrc, const u_char *edst, u_short *extracted_ethertype)
71 {
72         struct llc llc;
73         register u_short et;
74         u_int16_t control;
75         register int ret;
76
77         if (caplen < 3) {
78                 (void)printf("[|llc]");
79                 default_print((u_char *)p, caplen);
80                 return(0);
81         }
82
83         /* Watch out for possible alignment problems */
84         memcpy((char *)&llc, (char *)p, min(caplen, sizeof(llc)));
85
86         if (llc.ssap == LLCSAP_GLOBAL && llc.dsap == LLCSAP_GLOBAL) {
87                 /*
88                  * This is an Ethernet_802.3 IPX frame; it has an
89                  * 802.3 header (i.e., an Ethernet header where the
90                  * type/length field is <= ETHERMTU, i.e. it's a length
91                  * field, not a type field), but has no 802.2 header -
92                  * the IPX packet starts right after the Ethernet header,
93                  * with a signature of two bytes of 0xFF (which is
94                  * LLCSAP_GLOBAL).
95                  *
96                  * (It might also have been an Ethernet_802.3 IPX at
97                  * one time, but got bridged onto another network,
98                  * such as an 802.11 network; this has appeared in at
99                  * least one capture file.)
100                  */
101                 ipx_print(p, length);
102                 return (1);
103         }
104
105         if (llc.ssap == LLCSAP_8021D && llc.dsap == LLCSAP_8021D) {
106                 stp_print(p, length);
107                 return (1);
108         }
109
110         if (llc.ssap == LLCSAP_IPX && llc.dsap == LLCSAP_IPX &&
111             llc.llcui == LLC_UI) {
112                 /*
113                  * This is an Ethernet_802.2 IPX frame, with an 802.3
114                  * header and an 802.2 LLC header with the source and
115                  * destination SAPs being the IPX SAP.
116                  *
117                  * Skip DSAP, LSAP, and control field.
118                  */
119                 p += 3;
120                 length -= 3;
121                 caplen -= 3;
122                 ipx_print(p, length);
123                 return (1);
124         }
125
126 #ifdef TCPDUMP_DO_SMB
127         if (llc.ssap == LLCSAP_NETBEUI && llc.dsap == LLCSAP_NETBEUI
128             && (!(llc.llcu & LLC_S_FMT) || llc.llcu == LLC_U_FMT)) {
129                 /*
130                  * we don't actually have a full netbeui parser yet, but the
131                  * smb parser can handle many smb-in-netbeui packets, which
132                  * is very useful, so we call that
133                  *
134                  * We don't call it for S frames, however, just I frames
135                  * (which are frames that don't have the low-order bit,
136                  * LLC_S_FMT, set in the first byte of the control field)
137                  * and UI frames (whose control field is just 3, LLC_U_FMT).
138                  */
139
140                 /*
141                  * Skip the DSAP and LSAP.
142                  */
143                 p += 2;
144                 length -= 2;
145                 caplen -= 2;
146
147                 /*
148                  * OK, what type of LLC frame is this?  The length
149                  * of the control field depends on that - I frames
150                  * have a two-byte control field, and U frames have
151                  * a one-byte control field.
152                  */
153                 if (llc.llcu == LLC_U_FMT) {
154                         control = llc.llcu;
155                         p += 1;
156                         length -= 1;
157                         caplen -= 1;
158                 } else {
159                         /*
160                          * The control field in I and S frames is
161                          * little-endian.
162                          */
163                         control = EXTRACT_LE_16BITS(&llc.llcu);
164                         p += 2;
165                         length -= 2;
166                         caplen -= 2;
167                 }
168                 netbeui_print(control, p, length);
169                 return (1);
170         }
171 #endif
172         if (llc.ssap == LLCSAP_ISONS && llc.dsap == LLCSAP_ISONS
173             && llc.llcui == LLC_UI) {
174                 isoclns_print(p + 3, length - 3, caplen - 3, esrc, edst);
175                 return (1);
176         }
177
178         if (llc.ssap == LLCSAP_SNAP && llc.dsap == LLCSAP_SNAP
179             && llc.llcui == LLC_UI) {
180                 u_int32_t orgcode;
181
182                 if (caplen < sizeof(llc)) {
183                         (void)printf("[|llc-snap]");
184                         default_print((u_char *)p, caplen);
185                         return (0);
186                 }
187                 if (vflag)
188                         (void)printf("snap %s ", protoid_string(llc.llcpi));
189
190                 caplen -= sizeof(llc);
191                 length -= sizeof(llc);
192                 p += sizeof(llc);
193
194                 orgcode = EXTRACT_24BITS(&llc.llc_orgcode[0]);
195                 et = EXTRACT_16BITS(&llc.llc_ethertype[0]);
196                 switch (orgcode) {
197                 case OUI_ENCAP_ETHER:
198                 case OUI_CISCO_90:
199                         /*
200                          * This is an encapsulated Ethernet packet,
201                          * or a packet bridged by some piece of
202                          * Cisco hardware; the protocol ID is
203                          * an Ethernet protocol type.
204                          */
205                         ret = ether_encap_print(et, p, length, caplen,
206                             extracted_ethertype);
207                         if (ret)
208                                 return (ret);
209                         break;
210
211                 case OUI_APPLETALK:
212                         if (et == ETHERTYPE_ATALK) {
213                                 /*
214                                  * No, I have no idea why Apple used one
215                                  * of their own OUIs, rather than
216                                  * 0x000000, and an Ethernet packet
217                                  * type, for Appletalk data packets,
218                                  * but used 0x000000 and an Ethernet
219                                  * packet type for AARP packets.
220                                  */
221                                 ret = ether_encap_print(et, p, length, caplen,
222                                     extracted_ethertype);
223                                 if (ret)
224                                         return (ret);
225                         }
226                         break;
227
228                 case OUI_CISCO:
229                         if (et == ETHERTYPE_CISCO_CDP) {
230                                 cdp_print(p, length, caplen, esrc, edst);
231                                 return 1;
232                         }
233                         break;
234                 }
235         }
236
237         if ((llc.ssap & ~LLC_GSAP) == llc.dsap) {
238                 if (eflag || esrc == NULL || edst == NULL)
239                         (void)printf("%s ", llcsap_string(llc.dsap));
240                 else
241                         (void)printf("%s > %s %s ",
242                                         etheraddr_string(esrc),
243                                         etheraddr_string(edst),
244                                         llcsap_string(llc.dsap));
245         } else {
246                 if (eflag || esrc == NULL || edst == NULL)
247                         (void)printf("%s > %s ",
248                                 llcsap_string(llc.ssap & ~LLC_GSAP),
249                                 llcsap_string(llc.dsap));
250                 else
251                         (void)printf("%s %s > %s %s ",
252                                 etheraddr_string(esrc),
253                                 llcsap_string(llc.ssap & ~LLC_GSAP),
254                                 etheraddr_string(edst),
255                                 llcsap_string(llc.dsap));
256         }
257
258         if ((llc.llcu & LLC_U_FMT) == LLC_U_FMT) {
259                 u_int16_t cmd;
260                 const char *m;
261                 char f;
262
263                 cmd = LLC_U_CMD(llc.llcu);
264                 m = tok2str(cmd2str, "%02x", cmd);
265                 switch ((llc.ssap & LLC_GSAP) | (llc.llcu & LLC_U_POLL)) {
266                         case 0:                 f = 'C'; break;
267                         case LLC_GSAP:          f = 'R'; break;
268                         case LLC_U_POLL:        f = 'P'; break;
269                         case LLC_GSAP|LLC_U_POLL: f = 'F'; break;
270                         default:                f = '?'; break;
271                 }
272
273                 printf("%s/%c", m, f);
274
275                 p += 3;
276                 length -= 3;
277                 caplen -= 3;
278
279                 if ((llc.llcu & ~LLC_U_POLL) == LLC_XID) {
280                         if (*p == LLC_XID_FI) {
281                                 printf(": %02x %02x", p[1], p[2]);
282                                 p += 3;
283                                 length -= 3;
284                                 caplen -= 3;
285                         }
286                 }
287         } else {
288                 char f;
289
290                 /*
291                  * The control field in I and S frames is little-endian.
292                  */
293                 control = EXTRACT_LE_16BITS(&llc.llcu);
294                 switch ((llc.ssap & LLC_GSAP) | (control & LLC_IS_POLL)) {
295                         case 0:                 f = 'C'; break;
296                         case LLC_GSAP:          f = 'R'; break;
297                         case LLC_IS_POLL:       f = 'P'; break;
298                         case LLC_GSAP|LLC_IS_POLL: f = 'F'; break;
299                         default:                f = '?'; break;
300                 }
301
302                 if ((control & LLC_S_FMT) == LLC_S_FMT) {
303                         static char *llc_s[] = { "rr", "rej", "rnr", "03" };
304                         (void)printf("%s (r=%d,%c)",
305                                 llc_s[LLC_S_CMD(control)],
306                                 LLC_IS_NR(control),
307                                 f);
308                 } else {
309                         (void)printf("I (s=%d,r=%d,%c)",
310                                 LLC_I_NS(control),
311                                 LLC_IS_NR(control),
312                                 f);
313                 }
314                 p += 4;
315                 length -= 4;
316                 caplen -= 4;
317         }
318         (void)printf(" len=%d", length);
319         if (caplen > 0 && !qflag) {
320                 default_print_unaligned(p, caplen);
321         }
322         return(1);
323 }