]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/tcpdump/print-llc.c
Fix merge conflicts, and because this still has a zillion warnings,
[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.32 2000/12/18 07:55:36 guy 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
52 static struct tok cmd2str[] = {
53         { LLC_UI,       "ui" },
54         { LLC_TEST,     "test" },
55         { LLC_XID,      "xid" },
56         { LLC_UA,       "ua" },
57         { LLC_DISC,     "disc" },
58         { LLC_DM,       "dm" },
59         { LLC_SABME,    "sabme" },
60         { LLC_FRMR,     "frmr" },
61         { 0,            NULL }
62 };
63
64 /*
65  * Returns non-zero IFF it succeeds in printing the header
66  */
67 int
68 llc_print(const u_char *p, u_int length, u_int caplen,
69           const u_char *esrc, const u_char *edst, u_short *extracted_ethertype)
70 {
71         struct llc llc;
72         register u_short et;
73         u_int16_t control;
74         register int ret;
75
76         if (caplen < 3) {
77                 (void)printf("[|llc]");
78                 default_print((u_char *)p, caplen);
79                 return(0);
80         }
81
82         /* Watch out for possible alignment problems */
83         memcpy((char *)&llc, (char *)p, min(caplen, sizeof(llc)));
84
85         if (llc.ssap == LLCSAP_GLOBAL && llc.dsap == LLCSAP_GLOBAL) {
86                 ipx_print(p, length);
87                 return (1);
88         }
89
90         /* Cisco Discovery Protocol  - SNAP & ether type 0x2000 */
91         if(llc.ssap == LLCSAP_SNAP && llc.dsap == LLCSAP_SNAP &&
92                 llc.llcui == LLC_UI && 
93                 llc.ethertype[0] == 0x20 && llc.ethertype[1] == 0x00 ) {
94                     cdp_print( p, length, caplen, esrc, edst);
95                     return (1);
96         }
97
98         if (llc.ssap == LLCSAP_8021D && llc.dsap == LLCSAP_8021D) {
99                 stp_print(p, length);
100                 return (1);
101         }
102         if (llc.ssap == 0xf0 && llc.dsap == 0xf0
103             && (!(llc.llcu & LLC_S_FMT) || llc.llcu == LLC_U_FMT)) {
104                 /*
105                  * we don't actually have a full netbeui parser yet, but the
106                  * smb parser can handle many smb-in-netbeui packets, which
107                  * is very useful, so we call that
108                  *
109                  * We don't call it for S frames, however, just I frames
110                  * (which are frames that don't have the low-order bit,
111                  * LLC_S_FMT, set in the first byte of the control field)
112                  * and UI frames (whose control field is just 3, LLC_U_FMT).
113                  */
114
115                 /*
116                  * Skip the DSAP and LSAP.
117                  */
118                 p += 2;
119                 length -= 2;
120                 caplen -= 2;
121
122                 /*
123                  * OK, what type of LLC frame is this?  The length
124                  * of the control field depends on that - I frames
125                  * have a two-byte control field, and U frames have
126                  * a one-byte control field.
127                  */
128                 if (llc.llcu == LLC_U_FMT) {
129                         control = llc.llcu;
130                         p += 1;
131                         length -= 1;
132                         caplen -= 1;
133                 } else {
134                         /*
135                          * The control field in I and S frames is
136                          * little-endian.
137                          */
138                         control = EXTRACT_LE_16BITS(&llc.llcu);
139                         p += 2;
140                         length -= 2;
141                         caplen -= 2;
142                 }
143                 netbeui_print(control, p, p + min(caplen, length));
144                 return (1);
145         }
146         if (llc.ssap == LLCSAP_ISONS && llc.dsap == LLCSAP_ISONS
147             && llc.llcui == LLC_UI) {
148                 isoclns_print(p + 3, length - 3, caplen - 3, esrc, edst);
149                 return (1);
150         }
151
152         if (llc.ssap == LLCSAP_SNAP && llc.dsap == LLCSAP_SNAP
153             && llc.llcui == LLC_UI) {
154                 if (caplen < sizeof(llc)) {
155                         (void)printf("[|llc-snap]");
156                         default_print((u_char *)p, caplen);
157                         return (0);
158                 }
159                 if (vflag)
160                         (void)printf("snap %s ", protoid_string(llc.llcpi));
161
162                 caplen -= sizeof(llc);
163                 length -= sizeof(llc);
164                 p += sizeof(llc);
165
166                 /* This is an encapsulated Ethernet packet */
167                 et = EXTRACT_16BITS(&llc.ethertype[0]);
168                 ret = ether_encap_print(et, p, length, caplen,
169                     extracted_ethertype);
170                 if (ret)
171                         return (ret);
172         }
173
174         if ((llc.ssap & ~LLC_GSAP) == llc.dsap) {
175                 if (eflag)
176                         (void)printf("%s ", llcsap_string(llc.dsap));
177                 else
178                         (void)printf("%s > %s %s ",
179                                         etheraddr_string(esrc),
180                                         etheraddr_string(edst),
181                                         llcsap_string(llc.dsap));
182         } else {
183                 if (eflag)
184                         (void)printf("%s > %s ",
185                                 llcsap_string(llc.ssap & ~LLC_GSAP),
186                                 llcsap_string(llc.dsap));
187                 else
188                         (void)printf("%s %s > %s %s ",
189                                 etheraddr_string(esrc),
190                                 llcsap_string(llc.ssap & ~LLC_GSAP),
191                                 etheraddr_string(edst),
192                                 llcsap_string(llc.dsap));
193         }
194
195         if ((llc.llcu & LLC_U_FMT) == LLC_U_FMT) {
196                 u_int16_t cmd;
197                 const char *m;
198                 char f;
199
200                 cmd = LLC_U_CMD(llc.llcu);
201                 m = tok2str(cmd2str, "%02x", cmd);
202                 switch ((llc.ssap & LLC_GSAP) | (llc.llcu & LLC_U_POLL)) {
203                         case 0:                 f = 'C'; break;
204                         case LLC_GSAP:          f = 'R'; break;
205                         case LLC_U_POLL:        f = 'P'; break;
206                         case LLC_GSAP|LLC_U_POLL: f = 'F'; break;
207                         default:                f = '?'; break;
208                 }
209
210                 printf("%s/%c", m, f);
211
212                 p += 3;
213                 length -= 3;
214                 caplen -= 3;
215
216                 if ((llc.llcu & ~LLC_U_POLL) == LLC_XID) {
217                         if (*p == LLC_XID_FI) {
218                                 printf(": %02x %02x", p[1], p[2]);
219                                 p += 3;
220                                 length -= 3;
221                                 caplen -= 3;
222                         }
223                 }
224
225                 if (cmd == LLC_UI && f == 'C') {
226                         /*
227                          * we don't have a proper ipx decoder yet, but there
228                          * is a partial one in the smb code
229                          */
230                         ipx_netbios_print(p,p+min(caplen,length));
231                 }
232         } else {
233                 char f;
234
235                 /*
236                  * The control field in I and S frames is little-endian.
237                  */
238                 control = EXTRACT_LE_16BITS(&llc.llcu);
239                 switch ((llc.ssap & LLC_GSAP) | (control & LLC_IS_POLL)) {
240                         case 0:                 f = 'C'; break;
241                         case LLC_GSAP:          f = 'R'; break;
242                         case LLC_IS_POLL:       f = 'P'; break;
243                         case LLC_GSAP|LLC_IS_POLL: f = 'F'; break;
244                         default:                f = '?'; break;
245                 }
246
247                 if ((control & LLC_S_FMT) == LLC_S_FMT) {
248                         static char *llc_s[] = { "rr", "rej", "rnr", "03" };
249                         (void)printf("%s (r=%d,%c)",
250                                 llc_s[LLC_S_CMD(control)],
251                                 LLC_IS_NR(control),
252                                 f);
253                 } else {
254                         (void)printf("I (s=%d,r=%d,%c)",
255                                 LLC_I_NS(control),
256                                 LLC_IS_NR(control),
257                                 f);
258                 }
259                 p += 4;
260                 length -= 4;
261                 caplen -= 4;
262         }
263         (void)printf(" len=%d", length);
264         if (caplen > 0 && !qflag) {
265                 default_print_unaligned(p, caplen);
266         }
267         return(1);
268 }