print-ether.c revision 190207
1/*
2 * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 2000
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 * $FreeBSD: head/contrib/tcpdump/print-ether.c 190207 2009-03-21 18:30:25Z rpaulo $
22 */
23#ifndef lint
24static const char rcsid[] _U_ =
25    "@(#) $Header: /tcpdump/master/tcpdump/print-ether.c,v 1.105.2.1 2008-02-06 10:49:22 guy Exp $ (LBL)";
26#endif
27
28#ifdef HAVE_CONFIG_H
29#include "config.h"
30#endif
31
32#include <tcpdump-stdinc.h>
33
34#include <stdio.h>
35#include <pcap.h>
36
37#include "interface.h"
38#include "addrtoname.h"
39#include "ethertype.h"
40
41#include "ether.h"
42
43const struct tok ethertype_values[] = {
44    { ETHERTYPE_IP,		"IPv4" },
45    { ETHERTYPE_MPLS,		"MPLS unicast" },
46    { ETHERTYPE_MPLS_MULTI,	"MPLS multicast" },
47    { ETHERTYPE_IPV6,		"IPv6" },
48    { ETHERTYPE_8021Q,		"802.1Q" },
49    { ETHERTYPE_VMAN,		"VMAN" },
50    { ETHERTYPE_PUP,            "PUP" },
51    { ETHERTYPE_ARP,            "ARP"},
52    { ETHERTYPE_REVARP,         "Reverse ARP"},
53    { ETHERTYPE_NS,             "NS" },
54    { ETHERTYPE_SPRITE,         "Sprite" },
55    { ETHERTYPE_TRAIL,          "Trail" },
56    { ETHERTYPE_MOPDL,          "MOP DL" },
57    { ETHERTYPE_MOPRC,          "MOP RC" },
58    { ETHERTYPE_DN,             "DN" },
59    { ETHERTYPE_LAT,            "LAT" },
60    { ETHERTYPE_SCA,            "SCA" },
61    { ETHERTYPE_LANBRIDGE,      "Lanbridge" },
62    { ETHERTYPE_DECDNS,         "DEC DNS" },
63    { ETHERTYPE_DECDTS,         "DEC DTS" },
64    { ETHERTYPE_VEXP,           "VEXP" },
65    { ETHERTYPE_VPROD,          "VPROD" },
66    { ETHERTYPE_ATALK,          "Appletalk" },
67    { ETHERTYPE_AARP,           "Appletalk ARP" },
68    { ETHERTYPE_IPX,            "IPX" },
69    { ETHERTYPE_PPP,            "PPP" },
70    { ETHERTYPE_MPCP,           "MPCP" },
71    { ETHERTYPE_SLOW,           "Slow Protocols" },
72    { ETHERTYPE_PPPOED,         "PPPoE D" },
73    { ETHERTYPE_PPPOES,         "PPPoE S" },
74    { ETHERTYPE_EAPOL,          "EAPOL" },
75    { ETHERTYPE_RRCP,           "RRCP" },
76    { ETHERTYPE_JUMBO,          "Jumbo" },
77    { ETHERTYPE_LOOPBACK,       "Loopback" },
78    { ETHERTYPE_ISO,            "OSI" },
79    { ETHERTYPE_GRE_ISO,        "GRE-OSI" },
80    { ETHERTYPE_CFM_OLD,        "CFM (old)" },
81    { ETHERTYPE_CFM,            "CFM" },
82    { ETHERTYPE_LLDP,           "LLDP" },
83    { 0, NULL}
84};
85
86static inline void
87ether_hdr_print(register const u_char *bp, u_int length)
88{
89	register const struct ether_header *ep;
90	ep = (const struct ether_header *)bp;
91
92	(void)printf("%s > %s",
93		     etheraddr_string(ESRC(ep)),
94		     etheraddr_string(EDST(ep)));
95
96	if (!qflag) {
97	        if (ntohs(ep->ether_type) <= ETHERMTU)
98		          (void)printf(", 802.3");
99                else
100		          (void)printf(", ethertype %s (0x%04x)",
101				       tok2str(ethertype_values,"Unknown", ntohs(ep->ether_type)),
102                                       ntohs(ep->ether_type));
103        } else {
104                if (ntohs(ep->ether_type) <= ETHERMTU)
105                          (void)printf(", 802.3");
106                else
107                          (void)printf(", %s", tok2str(ethertype_values,"Unknown Ethertype (0x%04x)", ntohs(ep->ether_type)));
108        }
109
110	(void)printf(", length %u: ", length);
111}
112
113void
114ether_print(const u_char *p, u_int length, u_int caplen)
115{
116	struct ether_header *ep;
117	u_short ether_type;
118	u_short extracted_ether_type;
119
120	if (caplen < ETHER_HDRLEN) {
121		printf("[|ether]");
122		return;
123	}
124
125	if (eflag)
126		ether_hdr_print(p, length);
127
128	length -= ETHER_HDRLEN;
129	caplen -= ETHER_HDRLEN;
130	ep = (struct ether_header *)p;
131	p += ETHER_HDRLEN;
132
133	ether_type = ntohs(ep->ether_type);
134
135	/*
136	 * Is it (gag) an 802.3 encapsulation?
137	 */
138	if (ether_type <= ETHERMTU) {
139		/* Try to print the LLC-layer header & higher layers */
140		if (llc_print(p, length, caplen, ESRC(ep), EDST(ep),
141		    &extracted_ether_type) == 0) {
142			/* ether_type not known, print raw packet */
143			if (!eflag)
144				ether_hdr_print((u_char *)ep, length + ETHER_HDRLEN);
145
146			if (!suppress_default_print)
147				default_print(p, caplen);
148		}
149	} else if (ether_encap_print(ether_type, p, length, caplen,
150	    &extracted_ether_type) == 0) {
151		/* ether_type not known, print raw packet */
152		if (!eflag)
153			ether_hdr_print((u_char *)ep, length + ETHER_HDRLEN);
154
155		if (!suppress_default_print)
156			default_print(p, caplen);
157	}
158}
159
160/*
161 * This is the top level routine of the printer.  'p' points
162 * to the ether header of the packet, 'h->ts' is the timestamp,
163 * 'h->len' is the length of the packet off the wire, and 'h->caplen'
164 * is the number of bytes actually captured.
165 */
166u_int
167ether_if_print(const struct pcap_pkthdr *h, const u_char *p)
168{
169	ether_print(p, h->len, h->caplen);
170
171	return (ETHER_HDRLEN);
172}
173
174/*
175 * Prints the packet encapsulated in an Ethernet data segment
176 * (or an equivalent encapsulation), given the Ethernet type code.
177 *
178 * Returns non-zero if it can do so, zero if the ethertype is unknown.
179 *
180 * The Ethernet type code is passed through a pointer; if it was
181 * ETHERTYPE_8021Q, it gets updated to be the Ethernet type of
182 * the 802.1Q payload, for the benefit of lower layers that might
183 * want to know what it is.
184 */
185
186int
187ether_encap_print(u_short ether_type, const u_char *p,
188    u_int length, u_int caplen, u_short *extracted_ether_type)
189{
190 recurse:
191	*extracted_ether_type = ether_type;
192
193	switch (ether_type) {
194
195	case ETHERTYPE_IP:
196	        ip_print(gndo, p, length);
197		return (1);
198
199#ifdef INET6
200	case ETHERTYPE_IPV6:
201		ip6_print(p, length);
202		return (1);
203#endif /*INET6*/
204
205	case ETHERTYPE_ARP:
206	case ETHERTYPE_REVARP:
207  	        arp_print(gndo, p, length, caplen);
208		return (1);
209
210	case ETHERTYPE_DN:
211		decnet_print(p, length, caplen);
212		return (1);
213
214	case ETHERTYPE_ATALK:
215		if (vflag)
216			fputs("et1 ", stdout);
217		atalk_print(p, length);
218		return (1);
219
220	case ETHERTYPE_AARP:
221		aarp_print(p, length);
222		return (1);
223
224	case ETHERTYPE_IPX:
225		printf("(NOV-ETHII) ");
226		ipx_print(p, length);
227		return (1);
228
229	case ETHERTYPE_8021Q:
230	        if (eflag)
231		    printf("vlan %u, p %u%s, ",
232			   ntohs(*(u_int16_t *)p) & 0xfff,
233			   ntohs(*(u_int16_t *)p) >> 13,
234			   (ntohs(*(u_int16_t *)p) & 0x1000) ? ", CFI" : "");
235
236		ether_type = ntohs(*(u_int16_t *)(p + 2));
237		p += 4;
238		length -= 4;
239		caplen -= 4;
240
241		if (ether_type > ETHERMTU) {
242		        if (eflag)
243			        printf("ethertype %s, ",
244				       tok2str(ethertype_values,"0x%04x", ether_type));
245			goto recurse;
246		}
247
248		*extracted_ether_type = 0;
249
250		if (llc_print(p, length, caplen, p - 18, p - 12,
251		    extracted_ether_type) == 0) {
252                        ether_hdr_print(p - 18, length + 4);
253
254                        if (!suppress_default_print) {
255                                default_print(p - 18, caplen + 4);
256                        }
257		}
258
259
260		return (1);
261
262        case ETHERTYPE_JUMBO:
263                ether_type = ntohs(*(u_int16_t *)(p));
264                p += 2;
265                length -= 2;
266                caplen -= 2;
267
268                if (ether_type > ETHERMTU) {
269                    if (eflag)
270                        printf("ethertype %s, ",
271                               tok2str(ethertype_values,"0x%04x", ether_type));
272                    goto recurse;
273                }
274
275                *extracted_ether_type = 0;
276
277                if (llc_print(p, length, caplen, p - 16, p - 10,
278                              extracted_ether_type) == 0) {
279                    ether_hdr_print(p - 16, length + 2);
280
281                    if (!suppress_default_print) {
282                            default_print(p - 16, caplen + 2);
283                    }
284                }
285
286                return (1);
287
288        case ETHERTYPE_ISO:
289                isoclns_print(p+1, length-1, length-1);
290                return(1);
291
292	case ETHERTYPE_PPPOED:
293	case ETHERTYPE_PPPOES:
294	case ETHERTYPE_PPPOED2:
295	case ETHERTYPE_PPPOES2:
296		pppoe_print(p, length);
297		return (1);
298
299	case ETHERTYPE_EAPOL:
300	        eap_print(gndo, p, length);
301		return (1);
302
303	case ETHERTYPE_RRCP:
304	        rrcp_print(gndo, p - 14 , length + 14);
305		return (1);
306
307	case ETHERTYPE_PPP:
308		if (length) {
309			printf(": ");
310			ppp_print(p, length);
311		}
312		return (1);
313
314	case ETHERTYPE_MPCP:
315	        mpcp_print(p, length);
316		return (1);
317
318	case ETHERTYPE_SLOW:
319	        slow_print(p, length);
320		return (1);
321
322	case ETHERTYPE_CFM:
323	case ETHERTYPE_CFM_OLD:
324	        cfm_print(p, length);
325		return (1);
326
327	case ETHERTYPE_LLDP:
328	        lldp_print(p, length);
329		return (1);
330
331        case ETHERTYPE_LOOPBACK:
332                return (1);
333
334	case ETHERTYPE_MPLS:
335	case ETHERTYPE_MPLS_MULTI:
336		mpls_print(p, length);
337		return (1);
338
339	case ETHERTYPE_LAT:
340	case ETHERTYPE_SCA:
341	case ETHERTYPE_MOPRC:
342	case ETHERTYPE_MOPDL:
343		/* default_print for now */
344	default:
345		return (0);
346	}
347}
348
349
350/*
351 * Local Variables:
352 * c-style: whitesmith
353 * c-basic-offset: 8
354 * End:
355 */
356
357