1 /* $OpenBSD: print-llc.c,v 1.23 2023/02/28 10:04:50 claudio Exp $ */
2
3 /*
4 * Copyright (c) 1992, 1993, 1994, 1995, 1996, 1997
5 * The Regents of the University of California. All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that: (1) source code distributions
9 * retain the above copyright notice and this paragraph in its entirety, (2)
10 * distributions including binary code include the above copyright notice and
11 * this paragraph in its entirety in the documentation or other materials
12 * provided with the distribution, and (3) all advertising materials mentioning
13 * features or use of this software display the following acknowledgement:
14 * ``This product includes software developed by the University of California,
15 * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
16 * the University nor the names of its contributors may be used to endorse
17 * or promote products derived from this software without specific prior
18 * written permission.
19 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
20 * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
21 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
22 *
23 * Code by Matt Thomas, Digital Equipment Corporation
24 * with an awful lot of hacking by Jeffrey Mogul, DECWRL
25 */
26
27 #include <sys/time.h>
28
29 #include <netinet/in.h>
30
31 #include <ctype.h>
32 #include <netdb.h>
33 #include <signal.h>
34 #include <stdio.h>
35 #include <string.h>
36
37 #include "interface.h"
38 #include "addrtoname.h"
39 #include "extract.h" /* must come after interface.h */
40 #include "ethertype.h"
41
42 #include "llc.h"
43
44 static struct tok cmd2str[] = {
45 { LLC_UI, "ui" },
46 { LLC_TEST, "test" },
47 { LLC_XID, "xid" },
48 { LLC_UA, "ua" },
49 { LLC_DISC, "disc" },
50 { LLC_DM, "dm" },
51 { LLC_SABME, "sabme" },
52 { LLC_FRMR, "frmr" },
53 { 0, NULL }
54 };
55
56 /*
57 * Returns non-zero IFF it succeeds in printing the header
58 */
59 int
llc_print(const u_char * p,u_int length,u_int caplen,const u_char * esrc,const u_char * edst)60 llc_print(const u_char *p, u_int length, u_int caplen,
61 const u_char *esrc, const u_char *edst)
62 {
63 struct llc llc;
64 u_short et;
65 #if 0
66 u_short control;
67 #endif
68 int ret;
69
70 if (caplen < 3) {
71 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 ipx_print(p, length);
81 return (1);
82 }
83 #ifdef notyet
84 else if (p[0] == 0xf0 && p[1] == 0xf0)
85 netbios_print(p, length);
86 #endif
87 if (llc.ssap == LLCSAP_ISONS && llc.dsap == LLCSAP_ISONS
88 && llc.llcui == LLC_UI) {
89 isoclns_print(p + 3, length - 3, caplen - 3, esrc, edst);
90 return (1);
91 }
92
93 if (llc.ssap == LLCSAP_SNAP && llc.dsap == LLCSAP_SNAP
94 && llc.llcui == LLC_UI) {
95 if (caplen < sizeof(llc)) {
96 printf("[|llc-snap]");
97 default_print((u_char *)p, caplen);
98 return (0);
99 }
100
101 /* Cisco Discovery Protocol - SNAP & ether type 0x2000 */
102 if (llc.ethertype[0] == 0x20 && llc.ethertype[1] == 0x00) {
103 cdp_print(p, length, caplen, 8);
104 return (1);
105 }
106 /* Shared Spanning Tree Protocol - SNAP & ether type 0x010b */
107 if (llc.ethertype[0] == 0x01 && llc.ethertype[1] == 0x0b) {
108 stp_print(p, length);
109 return (1);
110 }
111
112 if (vflag)
113 printf("snap %s ", protoid_string(llc.llcpi));
114
115 caplen -= sizeof(llc);
116 length -= sizeof(llc);
117 p += sizeof(llc);
118
119 /* This is an encapsulated Ethernet packet */
120 et = EXTRACT_16BITS(&llc.ethertype[0]);
121
122 /*
123 * Some protocols have special handling if they are 802.3
124 * SNAP encapsulated vs vers II encapsulated. Handle
125 * those special protocols here, and hand the rest to
126 * print-ether.c so we don't have to duplicate
127 * all that code here.
128 */
129 switch (et) {
130 case ETHERTYPE_ATALK:
131 atalk_print(p, length);
132 ret = 1;
133 break;
134 default:
135 ret = ether_encap_print(et, p, length, caplen);
136 break;
137 }
138
139 if (ret)
140 return (ret);
141 }
142
143 if (llc.ssap == LLCSAP_8021D && llc.dsap == LLCSAP_8021D) {
144 stp_print(p, length);
145 return (1);
146 }
147
148 #if 0
149 if (llc.ssap == 0xf0 && llc.dsap == 0xf0) {
150 /*
151 * we don't actually have a full netbeui parser yet, but the
152 * smb parser can handle many smb-in-netbeui packets, which
153 * is very useful, so we call that
154 */
155
156 /*
157 * Skip the DSAP and LSAP.
158 */
159 p += 2;
160 length -= 2;
161 caplen -= 2;
162
163 /*
164 * OK, what type of LLC frame is this? The length
165 * of the control field depends on that - S or I
166 * frames have a two-byte control field, and U frames
167 * have a one-byte control field.
168 */
169 if ((llc.llcu & LLC_U_FMT) == LLC_U_FMT) {
170 control = llc.llcu;
171 p += 1;
172 length -= 1;
173 caplen -= 1;
174 } else {
175 control = llc.llcis;
176 p += 2;
177 length -= 2;
178 caplen -= 2;
179 }
180
181 netbeui_print(control, p, p + min(caplen, length));
182 return (1);
183 }
184 #endif
185
186 if ((llc.ssap & ~LLC_GSAP) == llc.dsap) {
187 if (eflag)
188 printf("%s ", llcsap_string(llc.dsap));
189 else
190 printf("%s > %s %s ",
191 etheraddr_string(esrc),
192 etheraddr_string(edst),
193 llcsap_string(llc.dsap));
194 } else {
195 if (eflag)
196 printf("%s > %s ",
197 llcsap_string(llc.ssap & ~LLC_GSAP),
198 llcsap_string(llc.dsap));
199 else
200 printf("%s %s > %s %s ",
201 etheraddr_string(esrc),
202 llcsap_string(llc.ssap & ~LLC_GSAP),
203 etheraddr_string(edst),
204 llcsap_string(llc.dsap));
205 }
206
207 if ((llc.llcu & LLC_U_FMT) == LLC_U_FMT) {
208 const char *m;
209 char f;
210 m = tok2str(cmd2str, "%02x", LLC_U_CMD(llc.llcu));
211 switch ((llc.ssap & LLC_GSAP) | (llc.llcu & LLC_U_POLL)) {
212 case 0: f = 'C'; break;
213 case LLC_GSAP: f = 'R'; break;
214 case LLC_U_POLL: f = 'P'; break;
215 case LLC_GSAP|LLC_U_POLL: f = 'F'; break;
216 default: f = '?'; break;
217 }
218
219 printf("%s/%c", m, f);
220
221 if (caplen < 6) {
222 default_print(p, caplen);
223 return (0);
224 }
225 p += 3;
226 length -= 3;
227 caplen -= 3;
228
229 if ((llc.llcu & ~LLC_U_POLL) == LLC_XID) {
230 if (*p == LLC_XID_FI) {
231 printf(": %02x %02x", p[1], p[2]);
232 p += 3;
233 length -= 3;
234 caplen -= 3;
235 }
236 }
237
238 #if 0
239 if (!strcmp(m,"ui") && f=='C') {
240 /*
241 * we don't have a proper ipx decoder yet, but there
242 * is a partial one in the smb code
243 */
244 ipx_netbios_print(p,p+min(caplen,length));
245 }
246 #endif
247
248 } else {
249 char f;
250 if (caplen < 4) {
251 default_print(p, caplen);
252 return (0);
253 }
254 llc.llcis = ntohs(llc.llcis);
255 switch ((llc.ssap & LLC_GSAP) | (llc.llcu & LLC_U_POLL)) {
256 case 0: f = 'C'; break;
257 case LLC_GSAP: f = 'R'; break;
258 case LLC_U_POLL: f = 'P'; break;
259 case LLC_GSAP|LLC_U_POLL: f = 'F'; break;
260 default: f = '?'; break;
261 }
262
263 if ((llc.llcu & LLC_S_FMT) == LLC_S_FMT) {
264 static char *llc_s[] = { "rr", "rej", "rnr", "03" };
265 printf("%s (r=%d,%c)",
266 llc_s[LLC_S_CMD(llc.llcis)],
267 LLC_IS_NR(llc.llcis),
268 f);
269 } else {
270 printf("I (s=%d,r=%d,%c)",
271 LLC_I_NS(llc.llcis),
272 LLC_IS_NR(llc.llcis),
273 f);
274 }
275 p += 4;
276 length -= 4;
277 caplen -= 4;
278 }
279 printf(" len=%d", length);
280 return(1);
281 }
282