1 |
|
|
/* $OpenBSD: print-llc.c,v 1.20 2015/11/16 00:16:39 mmcc 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 |
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 |
|
|
(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 |
|
|
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 |
|
|
(void)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, esrc, edst); |
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 |
|
|
(void)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 |
|
|
(void)printf("%s ", llcsap_string(llc.dsap)); |
189 |
|
|
else |
190 |
|
|
(void)printf("%s > %s %s ", |
191 |
|
|
etheraddr_string(esrc), |
192 |
|
|
etheraddr_string(edst), |
193 |
|
|
llcsap_string(llc.dsap)); |
194 |
|
|
} else { |
195 |
|
|
if (eflag) |
196 |
|
|
(void)printf("%s > %s ", |
197 |
|
|
llcsap_string(llc.ssap & ~LLC_GSAP), |
198 |
|
|
llcsap_string(llc.dsap)); |
199 |
|
|
else |
200 |
|
|
(void)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_unaligned(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_unaligned(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 |
|
|
(void)printf("%s (r=%d,%c)", |
266 |
|
|
llc_s[LLC_S_CMD(llc.llcis)], |
267 |
|
|
LLC_IS_NR(llc.llcis), |
268 |
|
|
f); |
269 |
|
|
} else { |
270 |
|
|
(void)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 |
|
|
(void)printf(" len=%d", length); |
280 |
|
|
return(1); |
281 |
|
|
} |