1 |
|
|
/* $OpenBSD: print-ether.c,v 1.31 2016/07/11 00:27:50 rzalamena Exp $ */ |
2 |
|
|
|
3 |
|
|
/* |
4 |
|
|
* Copyright (c) 1988, 1989, 1990, 1991, 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 |
|
|
|
24 |
|
|
#include <sys/time.h> |
25 |
|
|
#include <sys/socket.h> |
26 |
|
|
|
27 |
|
|
struct mbuf; |
28 |
|
|
struct rtentry; |
29 |
|
|
#include <net/if.h> |
30 |
|
|
|
31 |
|
|
#include <netinet/in.h> |
32 |
|
|
#include <netinet/if_ether.h> |
33 |
|
|
#include <netinet/ip.h> |
34 |
|
|
#include <netinet/ip_var.h> |
35 |
|
|
#include <netinet/udp.h> |
36 |
|
|
#include <netinet/udp_var.h> |
37 |
|
|
#include <netinet/tcp.h> |
38 |
|
|
|
39 |
|
|
#include <stdio.h> |
40 |
|
|
#include <pcap.h> |
41 |
|
|
|
42 |
|
|
#ifdef INET6 |
43 |
|
|
#include <netinet/ip6.h> |
44 |
|
|
#endif |
45 |
|
|
|
46 |
|
|
#include "interface.h" |
47 |
|
|
#include "addrtoname.h" |
48 |
|
|
#include "ethertype.h" |
49 |
|
|
#include "extract.h" |
50 |
|
|
|
51 |
|
|
const u_char *packetp; |
52 |
|
|
const u_char *snapend; |
53 |
|
|
|
54 |
|
|
void ether_macctl(const u_char *, u_int); |
55 |
|
|
|
56 |
|
|
void |
57 |
|
|
ether_print(const u_char *bp, u_int length) |
58 |
|
|
{ |
59 |
|
|
const struct ether_header *ep; |
60 |
|
|
|
61 |
|
|
ep = (const struct ether_header *)bp; |
62 |
|
|
if (qflag) { |
63 |
|
|
TCHECK2(*ep, 12); |
64 |
|
|
(void)printf("%s %s %d: ", |
65 |
|
|
etheraddr_string(ESRC(ep)), |
66 |
|
|
etheraddr_string(EDST(ep)), |
67 |
|
|
length); |
68 |
|
|
} else { |
69 |
|
|
TCHECK2(*ep, 14); |
70 |
|
|
(void)printf("%s %s %s %d: ", |
71 |
|
|
etheraddr_string(ESRC(ep)), |
72 |
|
|
etheraddr_string(EDST(ep)), |
73 |
|
|
etherproto_string(ep->ether_type), |
74 |
|
|
length); |
75 |
|
|
} |
76 |
|
|
return; |
77 |
|
|
trunc: |
78 |
|
|
printf("[|ether] "); |
79 |
|
|
} |
80 |
|
|
|
81 |
|
|
u_short extracted_ethertype; |
82 |
|
|
|
83 |
|
|
/* |
84 |
|
|
* This is the top level routine of the printer. 'p' is the points |
85 |
|
|
* to the ether header of the packet, 'tvp' is the timestamp, |
86 |
|
|
* 'length' is the length of the packet off the wire, and 'caplen' |
87 |
|
|
* is the number of bytes actually captured. |
88 |
|
|
*/ |
89 |
|
|
void |
90 |
|
|
ether_if_print(u_char *user, const struct pcap_pkthdr *h, const u_char *p) |
91 |
|
|
{ |
92 |
|
|
ts_print(&h->ts); |
93 |
|
|
|
94 |
|
|
/* |
95 |
|
|
* Some printers want to get back at the ethernet addresses, |
96 |
|
|
* and/or check that they're not walking off the end of the packet. |
97 |
|
|
* Rather than pass them all the way down, we set these globals. |
98 |
|
|
*/ |
99 |
|
|
snapend = p + h->caplen; |
100 |
|
|
|
101 |
|
|
ether_tryprint(p, h->len, 1); |
102 |
|
|
} |
103 |
|
|
|
104 |
|
|
void |
105 |
|
|
ether_tryprint(const u_char *p, u_int length, int first_header) |
106 |
|
|
{ |
107 |
|
|
struct ether_header *ep; |
108 |
|
|
u_int caplen = snapend - p; |
109 |
|
|
u_short ether_type; |
110 |
|
|
|
111 |
|
|
if (caplen < sizeof(struct ether_header)) { |
112 |
|
|
printf("[|ether]"); |
113 |
|
|
goto out; |
114 |
|
|
} |
115 |
|
|
|
116 |
|
|
if (eflag) |
117 |
|
|
ether_print(p, length); |
118 |
|
|
|
119 |
|
|
packetp = p; |
120 |
|
|
length -= sizeof(struct ether_header); |
121 |
|
|
caplen -= sizeof(struct ether_header); |
122 |
|
|
ep = (struct ether_header *)p; |
123 |
|
|
p += sizeof(struct ether_header); |
124 |
|
|
|
125 |
|
|
ether_type = ntohs(ep->ether_type); |
126 |
|
|
|
127 |
|
|
/* |
128 |
|
|
* Is it (gag) an 802.3 encapsulation? |
129 |
|
|
*/ |
130 |
|
|
extracted_ethertype = 0; |
131 |
|
|
if (ether_type <= ETHERMTU) { |
132 |
|
|
/* Try to print the LLC-layer header & higher layers */ |
133 |
|
|
if (llc_print(p, length, caplen, ESRC(ep), EDST(ep)) == 0) { |
134 |
|
|
/* ether_type not known, print raw packet */ |
135 |
|
|
if (!eflag) |
136 |
|
|
ether_print((u_char *)ep, length); |
137 |
|
|
if (extracted_ethertype) { |
138 |
|
|
printf("(LLC %s) ", |
139 |
|
|
etherproto_string(htons(extracted_ethertype))); |
140 |
|
|
} |
141 |
|
|
if (!xflag && !qflag) { |
142 |
|
|
if (eflag) |
143 |
|
|
default_print(packetp, |
144 |
|
|
snapend - packetp); |
145 |
|
|
else |
146 |
|
|
default_print(p, caplen); |
147 |
|
|
} |
148 |
|
|
} |
149 |
|
|
} else if (ether_encap_print(ether_type, p, length, caplen) == 0) { |
150 |
|
|
/* ether_type not known, print raw packet */ |
151 |
|
|
if (!eflag) |
152 |
|
|
ether_print((u_char *)ep, length + sizeof(*ep)); |
153 |
|
|
if (!xflag && !qflag) { |
154 |
|
|
if (eflag) |
155 |
|
|
default_print(packetp, snapend - packetp); |
156 |
|
|
else |
157 |
|
|
default_print(p, caplen); |
158 |
|
|
} |
159 |
|
|
} |
160 |
|
|
if (xflag && first_header) { |
161 |
|
|
if (eflag) |
162 |
|
|
default_print(packetp, snapend - packetp); |
163 |
|
|
else |
164 |
|
|
default_print(p, caplen); |
165 |
|
|
} |
166 |
|
|
out: |
167 |
|
|
if (first_header) |
168 |
|
|
putchar('\n'); |
169 |
|
|
} |
170 |
|
|
|
171 |
|
|
/* |
172 |
|
|
* Prints the packet encapsulated in an Ethernet data segment |
173 |
|
|
* (or an equivalent encapsulation), given the Ethernet type code. |
174 |
|
|
* |
175 |
|
|
* Returns non-zero if it can do so, zero if the ethertype is unknown. |
176 |
|
|
* |
177 |
|
|
* Stuffs the ether type into a global for the benefit of lower layers |
178 |
|
|
* that might want to know what it is. |
179 |
|
|
*/ |
180 |
|
|
|
181 |
|
|
int |
182 |
|
|
ether_encap_print(u_short ethertype, const u_char *p, |
183 |
|
|
u_int length, u_int caplen) |
184 |
|
|
{ |
185 |
|
|
recurse: |
186 |
|
|
extracted_ethertype = ethertype; |
187 |
|
|
|
188 |
|
|
switch (ethertype) { |
189 |
|
|
|
190 |
|
|
case ETHERTYPE_IP: |
191 |
|
|
ip_print(p, length); |
192 |
|
|
return (1); |
193 |
|
|
|
194 |
|
|
#ifdef INET6 |
195 |
|
|
case ETHERTYPE_IPV6: |
196 |
|
|
ip6_print(p, length); |
197 |
|
|
return (1); |
198 |
|
|
#endif /*INET6*/ |
199 |
|
|
|
200 |
|
|
case ETHERTYPE_ARP: |
201 |
|
|
case ETHERTYPE_REVARP: |
202 |
|
|
arp_print(p, length, caplen); |
203 |
|
|
return (1); |
204 |
|
|
|
205 |
|
|
case ETHERTYPE_DN: |
206 |
|
|
decnet_print(p, length, caplen); |
207 |
|
|
return (1); |
208 |
|
|
|
209 |
|
|
case ETHERTYPE_ATALK: |
210 |
|
|
if (vflag) |
211 |
|
|
fputs("et1 ", stdout); |
212 |
|
|
atalk_print_llap(p, length); |
213 |
|
|
return (1); |
214 |
|
|
|
215 |
|
|
case ETHERTYPE_AARP: |
216 |
|
|
aarp_print(p, length); |
217 |
|
|
return (1); |
218 |
|
|
|
219 |
|
|
case ETHERTYPE_8021Q: |
220 |
|
|
printf("802.1Q "); |
221 |
|
|
case ETHERTYPE_QINQ: |
222 |
|
|
if (ethertype == ETHERTYPE_QINQ) |
223 |
|
|
printf("QinQ s"); |
224 |
|
|
printf("vid %d pri %d%s", |
225 |
|
|
ntohs(*(unsigned short*)p)&0xFFF, |
226 |
|
|
ntohs(*(unsigned short*)p)>>13, |
227 |
|
|
(ntohs(*(unsigned short*)p)&0x1000) ? " cfi " : " "); |
228 |
|
|
ethertype = ntohs(*(unsigned short*)(p+2)); |
229 |
|
|
p += 4; |
230 |
|
|
length -= 4; |
231 |
|
|
caplen -= 4; |
232 |
|
|
if (ethertype > ETHERMTU) |
233 |
|
|
goto recurse; |
234 |
|
|
|
235 |
|
|
extracted_ethertype = 0; |
236 |
|
|
|
237 |
|
|
if (llc_print(p, length, caplen, p-18, p-12) == 0) { |
238 |
|
|
/* ether_type not known, print raw packet */ |
239 |
|
|
if (!eflag) |
240 |
|
|
ether_print(p-18, length+4); |
241 |
|
|
if (extracted_ethertype) { |
242 |
|
|
printf("(LLC %s) ", |
243 |
|
|
etherproto_string(htons(extracted_ethertype))); |
244 |
|
|
} |
245 |
|
|
if (!xflag && !qflag) |
246 |
|
|
default_print(p-18, caplen+4); |
247 |
|
|
} |
248 |
|
|
return (1); |
249 |
|
|
|
250 |
|
|
#ifdef PPP |
251 |
|
|
case ETHERTYPE_PPPOEDISC: |
252 |
|
|
case ETHERTYPE_PPPOE: |
253 |
|
|
pppoe_if_print(ethertype, p, length, caplen); |
254 |
|
|
return (1); |
255 |
|
|
#endif |
256 |
|
|
|
257 |
|
|
case ETHERTYPE_FLOWCONTROL: |
258 |
|
|
ether_macctl(p, length); |
259 |
|
|
return (1); |
260 |
|
|
|
261 |
|
|
case ETHERTYPE_MPLS: |
262 |
|
|
case ETHERTYPE_MPLS_MCAST: |
263 |
|
|
mpls_print(p, length); |
264 |
|
|
return (1); |
265 |
|
|
|
266 |
|
|
case ETHERTYPE_LLDP: |
267 |
|
|
lldp_print(p, length); |
268 |
|
|
return (1); |
269 |
|
|
|
270 |
|
|
case ETHERTYPE_SLOW: |
271 |
|
|
slow_print(p, length); |
272 |
|
|
return (1); |
273 |
|
|
|
274 |
|
|
case ETHERTYPE_LAT: |
275 |
|
|
case ETHERTYPE_SCA: |
276 |
|
|
case ETHERTYPE_MOPRC: |
277 |
|
|
case ETHERTYPE_MOPDL: |
278 |
|
|
/* default_print for now */ |
279 |
|
|
default: |
280 |
|
|
return (0); |
281 |
|
|
} |
282 |
|
|
} |
283 |
|
|
|
284 |
|
|
void |
285 |
|
|
ether_macctl(const u_char *p, u_int length) |
286 |
|
|
{ |
287 |
|
|
printf("MACCTL"); |
288 |
|
|
|
289 |
|
|
if (length < 2) |
290 |
|
|
goto trunc; |
291 |
|
|
if (EXTRACT_16BITS(p) == 0x0001) { |
292 |
|
|
u_int plen; |
293 |
|
|
|
294 |
|
|
printf(" PAUSE"); |
295 |
|
|
|
296 |
|
|
length -= 2; |
297 |
|
|
p += 2; |
298 |
|
|
if (length < 2) |
299 |
|
|
goto trunc; |
300 |
|
|
plen = 512 * EXTRACT_16BITS(p); |
301 |
|
|
printf(" quanta %u", plen); |
302 |
|
|
} else { |
303 |
|
|
printf(" unknown-opcode(0x%04x)", EXTRACT_16BITS(p)); |
304 |
|
|
} |
305 |
|
|
return; |
306 |
|
|
|
307 |
|
|
trunc: |
308 |
|
|
printf("[|MACCTL]"); |
309 |
|
|
} |