1 | #include <machine/rtems-bsd-user-space.h> |
---|
2 | |
---|
3 | /* |
---|
4 | * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 2000 |
---|
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 | * $FreeBSD$ |
---|
24 | */ |
---|
25 | #ifndef lint |
---|
26 | static const char rcsid[] _U_ = |
---|
27 | "@(#) $Header: /tcpdump/master/tcpdump/print-ether.c,v 1.106 2008-02-06 10:47:53 guy Exp $ (LBL)"; |
---|
28 | #endif |
---|
29 | |
---|
30 | #define NETDISSECT_REWORKED |
---|
31 | #ifdef HAVE_CONFIG_H |
---|
32 | #include "config.h" |
---|
33 | #endif |
---|
34 | |
---|
35 | #include <tcpdump-stdinc.h> |
---|
36 | |
---|
37 | #include <stdio.h> |
---|
38 | #include <pcap.h> |
---|
39 | |
---|
40 | #include "interface.h" |
---|
41 | #include "extract.h" |
---|
42 | #include "addrtoname.h" |
---|
43 | #include "ethertype.h" |
---|
44 | #include "ether.h" |
---|
45 | |
---|
46 | const struct tok ethertype_values[] = { |
---|
47 | { ETHERTYPE_IP, "IPv4" }, |
---|
48 | { ETHERTYPE_MPLS, "MPLS unicast" }, |
---|
49 | { ETHERTYPE_MPLS_MULTI, "MPLS multicast" }, |
---|
50 | { ETHERTYPE_IPV6, "IPv6" }, |
---|
51 | { ETHERTYPE_8021Q, "802.1Q" }, |
---|
52 | { ETHERTYPE_8021Q9100, "802.1Q-9100" }, |
---|
53 | { ETHERTYPE_8021QinQ, "802.1Q-QinQ" }, |
---|
54 | { ETHERTYPE_8021Q9200, "802.1Q-9200" }, |
---|
55 | { ETHERTYPE_VMAN, "VMAN" }, |
---|
56 | { ETHERTYPE_PUP, "PUP" }, |
---|
57 | { ETHERTYPE_ARP, "ARP"}, |
---|
58 | { ETHERTYPE_REVARP, "Reverse ARP"}, |
---|
59 | { ETHERTYPE_NS, "NS" }, |
---|
60 | { ETHERTYPE_SPRITE, "Sprite" }, |
---|
61 | { ETHERTYPE_TRAIL, "Trail" }, |
---|
62 | { ETHERTYPE_MOPDL, "MOP DL" }, |
---|
63 | { ETHERTYPE_MOPRC, "MOP RC" }, |
---|
64 | { ETHERTYPE_DN, "DN" }, |
---|
65 | { ETHERTYPE_LAT, "LAT" }, |
---|
66 | { ETHERTYPE_SCA, "SCA" }, |
---|
67 | { ETHERTYPE_TEB, "TEB" }, |
---|
68 | { ETHERTYPE_LANBRIDGE, "Lanbridge" }, |
---|
69 | { ETHERTYPE_DECDNS, "DEC DNS" }, |
---|
70 | { ETHERTYPE_DECDTS, "DEC DTS" }, |
---|
71 | { ETHERTYPE_VEXP, "VEXP" }, |
---|
72 | { ETHERTYPE_VPROD, "VPROD" }, |
---|
73 | { ETHERTYPE_ATALK, "Appletalk" }, |
---|
74 | { ETHERTYPE_AARP, "Appletalk ARP" }, |
---|
75 | { ETHERTYPE_IPX, "IPX" }, |
---|
76 | { ETHERTYPE_PPP, "PPP" }, |
---|
77 | { ETHERTYPE_MPCP, "MPCP" }, |
---|
78 | { ETHERTYPE_SLOW, "Slow Protocols" }, |
---|
79 | { ETHERTYPE_PPPOED, "PPPoE D" }, |
---|
80 | { ETHERTYPE_PPPOES, "PPPoE S" }, |
---|
81 | { ETHERTYPE_EAPOL, "EAPOL" }, |
---|
82 | { ETHERTYPE_RRCP, "RRCP" }, |
---|
83 | { ETHERTYPE_MS_NLB_HB, "MS NLB heartbeat" }, |
---|
84 | { ETHERTYPE_JUMBO, "Jumbo" }, |
---|
85 | { ETHERTYPE_LOOPBACK, "Loopback" }, |
---|
86 | { ETHERTYPE_ISO, "OSI" }, |
---|
87 | { ETHERTYPE_GRE_ISO, "GRE-OSI" }, |
---|
88 | { ETHERTYPE_CFM_OLD, "CFM (old)" }, |
---|
89 | { ETHERTYPE_CFM, "CFM" }, |
---|
90 | { ETHERTYPE_LLDP, "LLDP" }, |
---|
91 | { ETHERTYPE_TIPC, "TIPC"}, |
---|
92 | { 0, NULL} |
---|
93 | }; |
---|
94 | |
---|
95 | static inline void |
---|
96 | ether_hdr_print(netdissect_options *ndo, |
---|
97 | const u_char *bp, u_int length) |
---|
98 | { |
---|
99 | register const struct ether_header *ep; |
---|
100 | u_int16_t ether_type; |
---|
101 | |
---|
102 | ep = (const struct ether_header *)bp; |
---|
103 | |
---|
104 | (void)ND_PRINT((ndo, "%s > %s", |
---|
105 | etheraddr_string(ESRC(ep)), |
---|
106 | etheraddr_string(EDST(ep)))); |
---|
107 | |
---|
108 | ether_type = EXTRACT_16BITS(&ep->ether_type); |
---|
109 | if (!ndo->ndo_qflag) { |
---|
110 | if (ether_type <= ETHERMTU) |
---|
111 | (void)ND_PRINT((ndo, ", 802.3")); |
---|
112 | else |
---|
113 | (void)ND_PRINT((ndo, ", ethertype %s (0x%04x)", |
---|
114 | tok2str(ethertype_values,"Unknown", ether_type), |
---|
115 | ether_type)); |
---|
116 | } else { |
---|
117 | if (ether_type <= ETHERMTU) |
---|
118 | (void)ND_PRINT((ndo, ", 802.3")); |
---|
119 | else |
---|
120 | (void)ND_PRINT((ndo, ", %s", tok2str(ethertype_values,"Unknown Ethertype (0x%04x)", ether_type))); |
---|
121 | } |
---|
122 | |
---|
123 | (void)ND_PRINT((ndo, ", length %u: ", length)); |
---|
124 | } |
---|
125 | |
---|
126 | /* |
---|
127 | * Print an Ethernet frame. |
---|
128 | * This might be encapsulated within another frame; we might be passed |
---|
129 | * a pointer to a function that can print header information for that |
---|
130 | * frame's protocol, and an argument to pass to that function. |
---|
131 | */ |
---|
132 | void |
---|
133 | ether_print(netdissect_options *ndo, |
---|
134 | const u_char *p, u_int length, u_int caplen, |
---|
135 | void (*print_encap_header)(netdissect_options *ndo, const u_char *), const u_char *encap_header_arg) |
---|
136 | { |
---|
137 | struct ether_header *ep; |
---|
138 | u_int orig_length; |
---|
139 | u_short ether_type; |
---|
140 | u_short extracted_ether_type; |
---|
141 | |
---|
142 | if (caplen < ETHER_HDRLEN || length < ETHER_HDRLEN) { |
---|
143 | ND_PRINT((ndo, "[|ether]")); |
---|
144 | return; |
---|
145 | } |
---|
146 | |
---|
147 | if (ndo->ndo_eflag) { |
---|
148 | if (print_encap_header != NULL) |
---|
149 | (*print_encap_header)(ndo, encap_header_arg); |
---|
150 | ether_hdr_print(ndo, p, length); |
---|
151 | } |
---|
152 | orig_length = length; |
---|
153 | |
---|
154 | length -= ETHER_HDRLEN; |
---|
155 | caplen -= ETHER_HDRLEN; |
---|
156 | ep = (struct ether_header *)p; |
---|
157 | p += ETHER_HDRLEN; |
---|
158 | |
---|
159 | ether_type = EXTRACT_16BITS(&ep->ether_type); |
---|
160 | |
---|
161 | recurse: |
---|
162 | /* |
---|
163 | * Is it (gag) an 802.3 encapsulation? |
---|
164 | */ |
---|
165 | if (ether_type <= ETHERMTU) { |
---|
166 | /* Try to print the LLC-layer header & higher layers */ |
---|
167 | if (llc_print(p, length, caplen, ESRC(ep), EDST(ep), |
---|
168 | &extracted_ether_type) == 0) { |
---|
169 | /* ether_type not known, print raw packet */ |
---|
170 | if (!ndo->ndo_eflag) { |
---|
171 | if (print_encap_header != NULL) |
---|
172 | (*print_encap_header)(ndo, encap_header_arg); |
---|
173 | ether_hdr_print(ndo, (u_char *)ep, orig_length); |
---|
174 | } |
---|
175 | |
---|
176 | if (!ndo->ndo_suppress_default_print) |
---|
177 | ndo->ndo_default_print(ndo, p, caplen); |
---|
178 | } |
---|
179 | } else if (ether_type == ETHERTYPE_8021Q || |
---|
180 | ether_type == ETHERTYPE_8021Q9100 || |
---|
181 | ether_type == ETHERTYPE_8021Q9200 || |
---|
182 | ether_type == ETHERTYPE_8021QinQ) { |
---|
183 | /* |
---|
184 | * Print VLAN information, and then go back and process |
---|
185 | * the enclosed type field. |
---|
186 | */ |
---|
187 | if (caplen < 4 || length < 4) { |
---|
188 | ND_PRINT((ndo, "[|vlan]")); |
---|
189 | return; |
---|
190 | } |
---|
191 | if (ndo->ndo_eflag) { |
---|
192 | u_int16_t tag = EXTRACT_16BITS(p); |
---|
193 | |
---|
194 | ND_PRINT((ndo, "vlan %u, p %u%s, ", |
---|
195 | tag & 0xfff, |
---|
196 | tag >> 13, |
---|
197 | (tag & 0x1000) ? ", CFI" : "")); |
---|
198 | } |
---|
199 | |
---|
200 | ether_type = EXTRACT_16BITS(p + 2); |
---|
201 | if (ndo->ndo_eflag && ether_type > ETHERMTU) |
---|
202 | ND_PRINT((ndo, "ethertype %s, ", tok2str(ethertype_values,"0x%04x", ether_type))); |
---|
203 | p += 4; |
---|
204 | length -= 4; |
---|
205 | caplen -= 4; |
---|
206 | goto recurse; |
---|
207 | } else if (ether_type == ETHERTYPE_JUMBO) { |
---|
208 | /* |
---|
209 | * Alteon jumbo frames. |
---|
210 | * See |
---|
211 | * |
---|
212 | * http://tools.ietf.org/html/draft-ietf-isis-ext-eth-01 |
---|
213 | * |
---|
214 | * which indicates that, following the type field, |
---|
215 | * there's an LLC header and payload. |
---|
216 | */ |
---|
217 | /* Try to print the LLC-layer header & higher layers */ |
---|
218 | if (llc_print(p, length, caplen, ESRC(ep), EDST(ep), |
---|
219 | &extracted_ether_type) == 0) { |
---|
220 | /* ether_type not known, print raw packet */ |
---|
221 | if (!ndo->ndo_eflag) { |
---|
222 | if (print_encap_header != NULL) |
---|
223 | (*print_encap_header)(ndo, encap_header_arg); |
---|
224 | ether_hdr_print(ndo, (u_char *)ep, orig_length); |
---|
225 | } |
---|
226 | |
---|
227 | if (!ndo->ndo_suppress_default_print) |
---|
228 | ndo->ndo_default_print(ndo, p, caplen); |
---|
229 | } |
---|
230 | } else { |
---|
231 | if (ethertype_print(ndo, ether_type, p, length, caplen) == 0) { |
---|
232 | /* ether_type not known, print raw packet */ |
---|
233 | if (!ndo->ndo_eflag) { |
---|
234 | if (print_encap_header != NULL) |
---|
235 | (*print_encap_header)(ndo, encap_header_arg); |
---|
236 | ether_hdr_print(ndo, (u_char *)ep, orig_length); |
---|
237 | } |
---|
238 | |
---|
239 | if (!ndo->ndo_suppress_default_print) |
---|
240 | ndo->ndo_default_print(ndo, p, caplen); |
---|
241 | } |
---|
242 | } |
---|
243 | } |
---|
244 | |
---|
245 | /* |
---|
246 | * This is the top level routine of the printer. 'p' points |
---|
247 | * to the ether header of the packet, 'h->ts' is the timestamp, |
---|
248 | * 'h->len' is the length of the packet off the wire, and 'h->caplen' |
---|
249 | * is the number of bytes actually captured. |
---|
250 | */ |
---|
251 | u_int |
---|
252 | ether_if_print(netdissect_options *ndo, const struct pcap_pkthdr *h, |
---|
253 | const u_char *p) |
---|
254 | { |
---|
255 | ether_print(ndo, p, h->len, h->caplen, NULL, NULL); |
---|
256 | |
---|
257 | return (ETHER_HDRLEN); |
---|
258 | } |
---|
259 | |
---|
260 | /* |
---|
261 | * This is the top level routine of the printer. 'p' points |
---|
262 | * to the ether header of the packet, 'h->ts' is the timestamp, |
---|
263 | * 'h->len' is the length of the packet off the wire, and 'h->caplen' |
---|
264 | * is the number of bytes actually captured. |
---|
265 | * |
---|
266 | * This is for DLT_NETANALYZER, which has a 4-byte pseudo-header |
---|
267 | * before the Ethernet header. |
---|
268 | */ |
---|
269 | u_int |
---|
270 | netanalyzer_if_print(netdissect_options *ndo, const struct pcap_pkthdr *h, |
---|
271 | const u_char *p) |
---|
272 | { |
---|
273 | /* |
---|
274 | * Fail if we don't have enough data for the Hilscher pseudo-header. |
---|
275 | */ |
---|
276 | if (h->len < 4 || h->caplen < 4) { |
---|
277 | printf("[|netanalyzer]"); |
---|
278 | return (h->caplen); |
---|
279 | } |
---|
280 | |
---|
281 | /* Skip the pseudo-header. */ |
---|
282 | ether_print(ndo, p + 4, h->len - 4, h->caplen - 4, NULL, NULL); |
---|
283 | |
---|
284 | return (4 + ETHER_HDRLEN); |
---|
285 | } |
---|
286 | |
---|
287 | /* |
---|
288 | * This is the top level routine of the printer. 'p' points |
---|
289 | * to the ether header of the packet, 'h->ts' is the timestamp, |
---|
290 | * 'h->len' is the length of the packet off the wire, and 'h->caplen' |
---|
291 | * is the number of bytes actually captured. |
---|
292 | * |
---|
293 | * This is for DLT_NETANALYZER_TRANSPARENT, which has a 4-byte |
---|
294 | * pseudo-header, a 7-byte Ethernet preamble, and a 1-byte Ethernet SOF |
---|
295 | * before the Ethernet header. |
---|
296 | */ |
---|
297 | u_int |
---|
298 | netanalyzer_transparent_if_print(netdissect_options *ndo, |
---|
299 | const struct pcap_pkthdr *h, |
---|
300 | const u_char *p) |
---|
301 | { |
---|
302 | /* |
---|
303 | * Fail if we don't have enough data for the Hilscher pseudo-header, |
---|
304 | * preamble, and SOF. |
---|
305 | */ |
---|
306 | if (h->len < 12 || h->caplen < 12) { |
---|
307 | printf("[|netanalyzer-transparent]"); |
---|
308 | return (h->caplen); |
---|
309 | } |
---|
310 | |
---|
311 | /* Skip the pseudo-header, preamble, and SOF. */ |
---|
312 | ether_print(ndo, p + 12, h->len - 12, h->caplen - 12, NULL, NULL); |
---|
313 | |
---|
314 | return (12 + ETHER_HDRLEN); |
---|
315 | } |
---|
316 | |
---|
317 | /* |
---|
318 | * Prints the packet payload, given an Ethernet type code for the payload's |
---|
319 | * protocol. |
---|
320 | * |
---|
321 | * Returns non-zero if it can do so, zero if the ethertype is unknown. |
---|
322 | */ |
---|
323 | |
---|
324 | int |
---|
325 | ethertype_print(netdissect_options *ndo, |
---|
326 | u_short ether_type, const u_char *p, |
---|
327 | u_int length, u_int caplen) |
---|
328 | { |
---|
329 | switch (ether_type) { |
---|
330 | |
---|
331 | case ETHERTYPE_IP: |
---|
332 | ip_print(ndo, p, length); |
---|
333 | return (1); |
---|
334 | |
---|
335 | #ifdef INET6 |
---|
336 | case ETHERTYPE_IPV6: |
---|
337 | ip6_print(ndo, p, length); |
---|
338 | return (1); |
---|
339 | #endif /*INET6*/ |
---|
340 | |
---|
341 | case ETHERTYPE_ARP: |
---|
342 | case ETHERTYPE_REVARP: |
---|
343 | arp_print(ndo, p, length, caplen); |
---|
344 | return (1); |
---|
345 | |
---|
346 | case ETHERTYPE_DN: |
---|
347 | decnet_print(/*ndo,*/p, length, caplen); |
---|
348 | return (1); |
---|
349 | |
---|
350 | case ETHERTYPE_ATALK: |
---|
351 | if (ndo->ndo_vflag) |
---|
352 | fputs("et1 ", stdout); |
---|
353 | atalk_print(/*ndo,*/p, length); |
---|
354 | return (1); |
---|
355 | |
---|
356 | case ETHERTYPE_AARP: |
---|
357 | aarp_print(/*ndo,*/p, length); |
---|
358 | return (1); |
---|
359 | |
---|
360 | case ETHERTYPE_IPX: |
---|
361 | ND_PRINT((ndo, "(NOV-ETHII) ")); |
---|
362 | ipx_print(/*ndo,*/p, length); |
---|
363 | return (1); |
---|
364 | |
---|
365 | case ETHERTYPE_ISO: |
---|
366 | isoclns_print(/*ndo,*/p+1, length-1, length-1); |
---|
367 | return(1); |
---|
368 | |
---|
369 | case ETHERTYPE_PPPOED: |
---|
370 | case ETHERTYPE_PPPOES: |
---|
371 | case ETHERTYPE_PPPOED2: |
---|
372 | case ETHERTYPE_PPPOES2: |
---|
373 | pppoe_print(/*ndo,*/p, length); |
---|
374 | return (1); |
---|
375 | |
---|
376 | case ETHERTYPE_EAPOL: |
---|
377 | eap_print(ndo, p, length); |
---|
378 | return (1); |
---|
379 | |
---|
380 | case ETHERTYPE_RRCP: |
---|
381 | rrcp_print(ndo, p - 14 , length + 14); |
---|
382 | return (1); |
---|
383 | |
---|
384 | case ETHERTYPE_PPP: |
---|
385 | if (length) { |
---|
386 | printf(": "); |
---|
387 | ppp_print(/*ndo,*/p, length); |
---|
388 | } |
---|
389 | return (1); |
---|
390 | |
---|
391 | case ETHERTYPE_MPCP: |
---|
392 | mpcp_print(/*ndo,*/p, length); |
---|
393 | return (1); |
---|
394 | |
---|
395 | case ETHERTYPE_SLOW: |
---|
396 | slow_print(/*ndo,*/p, length); |
---|
397 | return (1); |
---|
398 | |
---|
399 | case ETHERTYPE_CFM: |
---|
400 | case ETHERTYPE_CFM_OLD: |
---|
401 | cfm_print(/*ndo,*/p, length); |
---|
402 | return (1); |
---|
403 | |
---|
404 | case ETHERTYPE_LLDP: |
---|
405 | lldp_print(/*ndo,*/p, length); |
---|
406 | return (1); |
---|
407 | |
---|
408 | case ETHERTYPE_LOOPBACK: |
---|
409 | return (1); |
---|
410 | |
---|
411 | case ETHERTYPE_MPLS: |
---|
412 | case ETHERTYPE_MPLS_MULTI: |
---|
413 | mpls_print(/*ndo,*/p, length); |
---|
414 | return (1); |
---|
415 | |
---|
416 | case ETHERTYPE_TIPC: |
---|
417 | tipc_print(ndo, p, length, caplen); |
---|
418 | return (1); |
---|
419 | |
---|
420 | case ETHERTYPE_MS_NLB_HB: |
---|
421 | msnlb_print(ndo, p, length); |
---|
422 | return (1); |
---|
423 | |
---|
424 | case ETHERTYPE_LAT: |
---|
425 | case ETHERTYPE_SCA: |
---|
426 | case ETHERTYPE_MOPRC: |
---|
427 | case ETHERTYPE_MOPDL: |
---|
428 | /* default_print for now */ |
---|
429 | default: |
---|
430 | return (0); |
---|
431 | } |
---|
432 | } |
---|
433 | |
---|
434 | |
---|
435 | /* |
---|
436 | * Local Variables: |
---|
437 | * c-style: whitesmith |
---|
438 | * c-basic-offset: 8 |
---|
439 | * End: |
---|
440 | */ |
---|
441 | |
---|