print-ether.c revision 162021
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 162021 2006-09-04 20:25:04Z sam $
22 */
23#ifndef lint
24static const char rcsid[] _U_ =
25    "@(#) $Header: /tcpdump/master/tcpdump/print-ether.c,v 1.95.2.4 2005/07/10 14:47:57 hannes 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_SLOW,           "Slow Protocols" },
71    { ETHERTYPE_PPPOED,         "PPPoE D" },
72    { ETHERTYPE_PPPOES,         "PPPoE S" },
73    { ETHERTYPE_EAPOL,          "EAPOL" },
74    { ETHERTYPE_JUMBO,          "Jumbo" },
75    { ETHERTYPE_LOOPBACK,       "Loopback" },
76    { ETHERTYPE_ISO,            "OSI" },
77    { ETHERTYPE_GRE_ISO,        "GRE-OSI" },
78    { 0, NULL}
79};
80
81static inline void
82ether_hdr_print(register const u_char *bp, u_int length)
83{
84	register const struct ether_header *ep;
85	ep = (const struct ether_header *)bp;
86
87	(void)printf("%s > %s",
88		     etheraddr_string(ESRC(ep)),
89		     etheraddr_string(EDST(ep)));
90
91	if (!qflag) {
92	        if (ntohs(ep->ether_type) <= ETHERMTU)
93		          (void)printf(", 802.3");
94                else
95		          (void)printf(", ethertype %s (0x%04x)",
96				       tok2str(ethertype_values,"Unknown", ntohs(ep->ether_type)),
97                                       ntohs(ep->ether_type));
98        } else {
99                if (ntohs(ep->ether_type) <= ETHERMTU)
100                          (void)printf(", 802.3");
101                else
102                          (void)printf(", %s", tok2str(ethertype_values,"Unknown Ethertype (0x%04x)", ntohs(ep->ether_type)));
103        }
104
105	(void)printf(", length %u: ", length);
106}
107
108void
109ether_print(const u_char *p, u_int length, u_int caplen)
110{
111	struct ether_header *ep;
112	u_short ether_type;
113	u_short extracted_ether_type;
114
115	if (caplen < ETHER_HDRLEN) {
116		printf("[|ether]");
117		return;
118	}
119
120	if (eflag)
121		ether_hdr_print(p, length);
122
123	length -= ETHER_HDRLEN;
124	caplen -= ETHER_HDRLEN;
125	ep = (struct ether_header *)p;
126	p += ETHER_HDRLEN;
127
128	ether_type = ntohs(ep->ether_type);
129
130	/*
131	 * Is it (gag) an 802.3 encapsulation?
132	 */
133	extracted_ether_type = 0;
134	if (ether_type <= ETHERMTU) {
135		/* Try to print the LLC-layer header & higher layers */
136		if (llc_print(p, length, caplen, ESRC(ep), EDST(ep),
137		    &extracted_ether_type) == 0) {
138			/* ether_type not known, print raw packet */
139			if (!eflag)
140				ether_hdr_print((u_char *)ep, length + ETHER_HDRLEN);
141
142			if (!suppress_default_print)
143				default_print(p, caplen);
144		}
145	} else if (ether_encap_print(ether_type, p, length, caplen,
146	    &extracted_ether_type) == 0) {
147		/* ether_type not known, print raw packet */
148		if (!eflag)
149			ether_hdr_print((u_char *)ep, length + ETHER_HDRLEN);
150
151		if (!suppress_default_print)
152			default_print(p, caplen);
153	}
154}
155
156/*
157 * This is the top level routine of the printer.  'p' points
158 * to the ether header of the packet, 'h->ts' is the timestamp,
159 * 'h->len' is the length of the packet off the wire, and 'h->caplen'
160 * is the number of bytes actually captured.
161 */
162u_int
163ether_if_print(const struct pcap_pkthdr *h, const u_char *p)
164{
165	ether_print(p, h->len, h->caplen);
166
167	return (ETHER_HDRLEN);
168}
169
170/*
171 * Prints the packet encapsulated in an Ethernet data segment
172 * (or an equivalent encapsulation), given the Ethernet type code.
173 *
174 * Returns non-zero if it can do so, zero if the ethertype is unknown.
175 *
176 * The Ethernet type code is passed through a pointer; if it was
177 * ETHERTYPE_8021Q, it gets updated to be the Ethernet type of
178 * the 802.1Q payload, for the benefit of lower layers that might
179 * want to know what it is.
180 */
181
182int
183ether_encap_print(u_short ether_type, const u_char *p,
184    u_int length, u_int caplen, u_short *extracted_ether_type)
185{
186 recurse:
187	*extracted_ether_type = ether_type;
188
189	switch (ether_type) {
190
191	case ETHERTYPE_IP:
192	        ip_print(gndo, p, length);
193		return (1);
194
195#ifdef INET6
196	case ETHERTYPE_IPV6:
197		ip6_print(p, length);
198		return (1);
199#endif /*INET6*/
200
201	case ETHERTYPE_ARP:
202	case ETHERTYPE_REVARP:
203  	        arp_print(gndo, p, length, caplen);
204		return (1);
205
206	case ETHERTYPE_DN:
207		decnet_print(p, length, caplen);
208		return (1);
209
210	case ETHERTYPE_ATALK:
211		if (vflag)
212			fputs("et1 ", stdout);
213		atalk_print(p, length);
214		return (1);
215
216	case ETHERTYPE_AARP:
217		aarp_print(p, length);
218		return (1);
219
220	case ETHERTYPE_IPX:
221		printf("(NOV-ETHII) ");
222		ipx_print(p, length);
223		return (1);
224
225	case ETHERTYPE_8021Q:
226	        if (eflag)
227		    printf("vlan %u, p %u%s, ",
228			   ntohs(*(u_int16_t *)p) & 0xfff,
229			   ntohs(*(u_int16_t *)p) >> 13,
230			   (ntohs(*(u_int16_t *)p) & 0x1000) ? ", CFI" : "");
231
232		ether_type = ntohs(*(u_int16_t *)(p + 2));
233		p += 4;
234		length -= 4;
235		caplen -= 4;
236
237		if (ether_type > ETHERMTU) {
238		        if (eflag)
239			        printf("ethertype %s, ",
240				       tok2str(ethertype_values,"0x%04x", ether_type));
241			goto recurse;
242		}
243
244		*extracted_ether_type = 0;
245
246		if (llc_print(p, length, caplen, p - 18, p - 12,
247		    extracted_ether_type) == 0) {
248				ether_hdr_print(p - 18, length + 4);
249		}
250
251		if (!suppress_default_print)
252		        default_print(p - 18, caplen + 4);
253
254		return (1);
255
256        case ETHERTYPE_JUMBO:
257                ether_type = ntohs(*(u_int16_t *)(p));
258                p += 2;
259                length -= 2;
260                caplen -= 2;
261
262                if (ether_type > ETHERMTU) {
263                    if (eflag)
264                        printf("ethertype %s, ",
265                               tok2str(ethertype_values,"0x%04x", ether_type));
266                    goto recurse;
267                }
268
269                *extracted_ether_type = 0;
270
271                if (llc_print(p, length, caplen, p - 16, p - 10,
272                              extracted_ether_type) == 0) {
273                    ether_hdr_print(p - 16, length + 2);
274                }
275
276                if (!suppress_default_print)
277                    default_print(p - 16, caplen + 2);
278
279                return (1);
280
281        case ETHERTYPE_ISO:
282                isoclns_print(p+1, length-1, length-1);
283                return(1);
284
285	case ETHERTYPE_PPPOED:
286	case ETHERTYPE_PPPOES:
287	case ETHERTYPE_PPPOED2:
288	case ETHERTYPE_PPPOES2:
289		pppoe_print(p, length);
290		return (1);
291
292	case ETHERTYPE_EAPOL:
293	        eap_print(gndo, p, length);
294		return (1);
295
296	case ETHERTYPE_PPP:
297		if (length) {
298			printf(": ");
299			ppp_print(p, length);
300		}
301		return (1);
302
303	case ETHERTYPE_SLOW:
304	        slow_print(p, length);
305		return (1);
306
307        case ETHERTYPE_LOOPBACK:
308                return (1);
309
310	case ETHERTYPE_MPLS:
311	case ETHERTYPE_MPLS_MULTI:
312		mpls_print(p, length);
313		return (1);
314
315	case ETHERTYPE_LAT:
316	case ETHERTYPE_SCA:
317	case ETHERTYPE_MOPRC:
318	case ETHERTYPE_MOPDL:
319		/* default_print for now */
320	default:
321		return (0);
322	}
323}
324
325
326/*
327 * Local Variables:
328 * c-style: whitesmith
329 * c-basic-offset: 8
330 * End:
331 */
332
333