print-ether.c revision 172686
1296853Sdes/*
276259Sgreen * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 2000
3126274Sdes *	The Regents of the University of California.  All rights reserved.
476259Sgreen *
5126274Sdes * Redistribution and use in source and binary forms, with or without
6126274Sdes * modification, are permitted provided that: (1) source code distributions
7126274Sdes * retain the above copyright notice and this paragraph in its entirety, (2)
876259Sgreen * distributions including binary code include the above copyright notice and
9126274Sdes * this paragraph in its entirety in the documentation or other materials
10126274Sdes * provided with the distribution, and (3) all advertising materials mentioning
11126274Sdes * features or use of this software display the following acknowledgement:
12126274Sdes * ``This product includes software developed by the University of California,
13126274Sdes * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
14126274Sdes * the University nor the names of its contributors may be used to endorse
15126274Sdes * or promote products derived from this software without specific prior
1676259Sgreen * written permission.
1776259Sgreen * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
1876259Sgreen * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
1976259Sgreen * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
20295367Sdes *
21162852Sdes * $FreeBSD: head/contrib/tcpdump/print-ether.c 172686 2007-10-16 02:31:48Z mlaier $
22162852Sdes */
23162852Sdes#ifndef lint
24162852Sdesstatic const char rcsid[] _U_ =
25162852Sdes    "@(#) $Header: /tcpdump/master/tcpdump/print-ether.c,v 1.95.2.6 2006/02/20 18:15:03 hannes Exp $ (LBL)";
26162852Sdes#endif
27162852Sdes
28162852Sdes#ifdef HAVE_CONFIG_H
29181111Sdes#include "config.h"
30181111Sdes#endif
31181111Sdes
3276259Sgreen#include <tcpdump-stdinc.h>
33181111Sdes
34162852Sdes#include <stdio.h>
35162852Sdes#include <pcap.h>
36162852Sdes
37162852Sdes#include "interface.h"
38162852Sdes#include "addrtoname.h"
39204917Sdes#include "ethertype.h"
40204917Sdes
41204917Sdes#include "ether.h"
42255767Sdes
43255767Sdesconst struct tok ethertype_values[] = {
44255767Sdes    { ETHERTYPE_IP,		"IPv4" },
45146998Sdes    { ETHERTYPE_MPLS,		"MPLS unicast" },
46146998Sdes    { ETHERTYPE_MPLS_MULTI,	"MPLS multicast" },
47146998Sdes    { ETHERTYPE_IPV6,		"IPv6" },
48146998Sdes    { ETHERTYPE_8021Q,		"802.1Q" },
49146998Sdes    { ETHERTYPE_VMAN,		"VMAN" },
50295367Sdes    { ETHERTYPE_PUP,            "PUP" },
51162852Sdes    { ETHERTYPE_ARP,            "ARP"},
52162852Sdes    { ETHERTYPE_REVARP,         "Reverse ARP"},
53162852Sdes    { ETHERTYPE_NS,             "NS" },
54162852Sdes    { ETHERTYPE_SPRITE,         "Sprite" },
55162852Sdes    { ETHERTYPE_TRAIL,          "Trail" },
56162852Sdes    { ETHERTYPE_MOPDL,          "MOP DL" },
57146998Sdes    { ETHERTYPE_MOPRC,          "MOP RC" },
58181111Sdes    { ETHERTYPE_DN,             "DN" },
59181111Sdes    { ETHERTYPE_LAT,            "LAT" },
60181111Sdes    { ETHERTYPE_SCA,            "SCA" },
61181111Sdes    { ETHERTYPE_LANBRIDGE,      "Lanbridge" },
6276259Sgreen    { ETHERTYPE_DECDNS,         "DEC DNS" },
6376259Sgreen    { ETHERTYPE_DECDTS,         "DEC DTS" },
6476259Sgreen    { ETHERTYPE_VEXP,           "VEXP" },
6592555Sdes    { ETHERTYPE_VPROD,          "VPROD" },
6676259Sgreen    { ETHERTYPE_ATALK,          "Appletalk" },
6776259Sgreen    { ETHERTYPE_AARP,           "Appletalk ARP" },
68295367Sdes    { ETHERTYPE_IPX,            "IPX" },
69295367Sdes    { ETHERTYPE_PPP,            "PPP" },
7076259Sgreen    { ETHERTYPE_SLOW,           "Slow Protocols" },
7176259Sgreen    { ETHERTYPE_PPPOED,         "PPPoE D" },
7276259Sgreen    { ETHERTYPE_PPPOES,         "PPPoE S" },
73204917Sdes    { ETHERTYPE_EAPOL,          "EAPOL" },
74294693Sdes    { ETHERTYPE_JUMBO,          "Jumbo" },
75204917Sdes    { ETHERTYPE_LOOPBACK,       "Loopback" },
76126274Sdes    { ETHERTYPE_ISO,            "OSI" },
77126274Sdes    { ETHERTYPE_GRE_ISO,        "GRE-OSI" },
78126274Sdes    { 0, NULL}
79126274Sdes};
80126274Sdes
81126274Sdesstatic inline void
82126274Sdesether_hdr_print(register const u_char *bp, u_int length)
83126274Sdes{
84126274Sdes	register const struct ether_header *ep;
85255767Sdes	ep = (const struct ether_header *)bp;
86255767Sdes
87255767Sdes	(void)printf("%s > %s",
88126274Sdes		     etheraddr_string(ESRC(ep)),
89128456Sdes		     etheraddr_string(EDST(ep)));
90126274Sdes
91204917Sdes	if (!qflag) {
92204917Sdes	        if (ntohs(ep->ether_type) <= ETHERMTU)
93204917Sdes		          (void)printf(", 802.3");
94295367Sdes                else
95255767Sdes		          (void)printf(", ethertype %s (0x%04x)",
96255767Sdes				       tok2str(ethertype_values,"Unknown", ntohs(ep->ether_type)),
97204917Sdes                                       ntohs(ep->ether_type));
98204917Sdes        } else {
99204917Sdes                if (ntohs(ep->ether_type) <= ETHERMTU)
100262566Sdes                          (void)printf(", 802.3");
101262566Sdes                else
102262566Sdes                          (void)printf(", %s", tok2str(ethertype_values,"Unknown Ethertype (0x%04x)", ntohs(ep->ether_type)));
103137015Sdes        }
104137015Sdes
105137015Sdes	(void)printf(", length %u: ", length);
106137015Sdes}
107137015Sdes
108137015Sdesvoid
109204917Sdesether_print(const u_char *p, u_int length, u_int caplen)
110204917Sdes{
111204917Sdes	struct ether_header *ep;
112204917Sdes	u_short ether_type;
113204917Sdes	u_short extracted_ether_type;
114204917Sdes
115126274Sdes	if (caplen < ETHER_HDRLEN) {
116126274Sdes		printf("[|ether]");
117126274Sdes		return;
11898937Sdes	}
11998937Sdes
120126274Sdes	if (eflag)
121126274Sdes		ether_hdr_print(p, length);
12276259Sgreen
123137015Sdes	length -= ETHER_HDRLEN;
124204917Sdes	caplen -= ETHER_HDRLEN;
125204917Sdes	ep = (struct ether_header *)p;
126204917Sdes	p += ETHER_HDRLEN;
127204917Sdes
128204917Sdes	ether_type = ntohs(ep->ether_type);
129204917Sdes
130204917Sdes	/*
131204917Sdes	 * Is it (gag) an 802.3 encapsulation?
132204917Sdes	 */
133113908Sdes	if (ether_type <= ETHERMTU) {
134204917Sdes		/* Try to print the LLC-layer header & higher layers */
135137015Sdes		if (llc_print(p, length, caplen, ESRC(ep), EDST(ep),
136137015Sdes		    &extracted_ether_type) == 0) {
137126274Sdes			/* ether_type not known, print raw packet */
138262566Sdes			if (!eflag)
139262566Sdes				ether_hdr_print((u_char *)ep, length + ETHER_HDRLEN);
140262566Sdes
141262566Sdes			if (!suppress_default_print)
142262566Sdes				default_print(p, caplen);
143262566Sdes		}
144262566Sdes	} else if (ether_encap_print(ether_type, p, length, caplen,
145262566Sdes	    &extracted_ether_type) == 0) {
146262566Sdes		/* ether_type not known, print raw packet */
147262566Sdes		if (!eflag)
148262566Sdes			ether_hdr_print((u_char *)ep, length + ETHER_HDRLEN);
149262566Sdes
150262566Sdes		if (!suppress_default_print)
151262566Sdes			default_print(p, caplen);
152262566Sdes	}
153262566Sdes}
154262566Sdes
155262566Sdes/*
156262566Sdes * This is the top level routine of the printer.  'p' points
157295367Sdes * to the ether header of the packet, 'h->ts' is the timestamp,
158262566Sdes * 'h->len' is the length of the packet off the wire, and 'h->caplen'
159295367Sdes * is the number of bytes actually captured.
160262566Sdes */
161262566Sdesu_int
162262566Sdesether_if_print(const struct pcap_pkthdr *h, const u_char *p)
163262566Sdes{
164262566Sdes	ether_print(p, h->len, h->caplen);
165262566Sdes
166262566Sdes	return (ETHER_HDRLEN);
167126274Sdes}
168126274Sdes
169126274Sdes/*
170126274Sdes * Prints the packet encapsulated in an Ethernet data segment
171204917Sdes * (or an equivalent encapsulation), given the Ethernet type code.
172126274Sdes *
173126274Sdes * Returns non-zero if it can do so, zero if the ethertype is unknown.
174204917Sdes *
175204917Sdes * The Ethernet type code is passed through a pointer; if it was
176204917Sdes * ETHERTYPE_8021Q, it gets updated to be the Ethernet type of
177204917Sdes * the 802.1Q payload, for the benefit of lower layers that might
178204917Sdes * want to know what it is.
179126274Sdes */
180204917Sdes
181204917Sdesint
182204917Sdesether_encap_print(u_short ether_type, const u_char *p,
183204917Sdes    u_int length, u_int caplen, u_short *extracted_ether_type)
184204917Sdes{
185204917Sdes recurse:
186204917Sdes	*extracted_ether_type = ether_type;
187204917Sdes
188204917Sdes	switch (ether_type) {
189204917Sdes
190204917Sdes	case ETHERTYPE_IP:
191204917Sdes	        ip_print(gndo, p, length);
192204917Sdes		return (1);
193204917Sdes
194204917Sdes#ifdef INET6
195221420Sdes	case ETHERTYPE_IPV6:
196204917Sdes		ip6_print(p, length);
197204917Sdes		return (1);
198204917Sdes#endif /*INET6*/
199204917Sdes
200215116Sdes	case ETHERTYPE_ARP:
201215116Sdes	case ETHERTYPE_REVARP:
202204917Sdes  	        arp_print(gndo, p, length, caplen);
203204917Sdes		return (1);
204204917Sdes
205204917Sdes	case ETHERTYPE_DN:
206255767Sdes		decnet_print(p, length, caplen);
207204917Sdes		return (1);
208295367Sdes
209204917Sdes	case ETHERTYPE_ATALK:
210204917Sdes		if (vflag)
211204917Sdes			fputs("et1 ", stdout);
212204917Sdes		atalk_print(p, length);
213204917Sdes		return (1);
214204917Sdes
215204917Sdes	case ETHERTYPE_AARP:
216126274Sdes		aarp_print(p, length);
217126274Sdes		return (1);
218204917Sdes
219126274Sdes	case ETHERTYPE_IPX:
220181111Sdes		printf("(NOV-ETHII) ");
22192555Sdes		ipx_print(p, length);
222137015Sdes		return (1);
223137015Sdes
224146998Sdes	case ETHERTYPE_8021Q:
225137015Sdes	        if (eflag)
226146998Sdes		    printf("vlan %u, p %u%s, ",
227146998Sdes			   ntohs(*(u_int16_t *)p) & 0xfff,
228137015Sdes			   ntohs(*(u_int16_t *)p) >> 13,
229137015Sdes			   (ntohs(*(u_int16_t *)p) & 0x1000) ? ", CFI" : "");
230137015Sdes
231137015Sdes		ether_type = ntohs(*(u_int16_t *)(p + 2));
232181111Sdes		p += 4;
233137015Sdes		length -= 4;
234137015Sdes		caplen -= 4;
235137015Sdes
236137015Sdes		if (ether_type > ETHERMTU) {
237146998Sdes		        if (eflag)
238137015Sdes			        printf("ethertype %s, ",
239255767Sdes				       tok2str(ethertype_values,"0x%04x", ether_type));
240137015Sdes			goto recurse;
241146998Sdes		}
242137015Sdes
243137015Sdes		*extracted_ether_type = 0;
244137015Sdes
245126274Sdes		if (llc_print(p, length, caplen, p - 18, p - 12,
246126274Sdes		    extracted_ether_type) == 0) {
247192595Sdes                        ether_hdr_print(p - 18, length + 4);
248192595Sdes
249192595Sdes                        if (!suppress_default_print) {
250192595Sdes                                default_print(p - 18, caplen + 4);
251192595Sdes                        }
252192595Sdes		}
253192595Sdes
254192595Sdes
255192595Sdes		return (1);
256295367Sdes
257295367Sdes        case ETHERTYPE_JUMBO:
258295367Sdes                ether_type = ntohs(*(u_int16_t *)(p));
259192595Sdes                p += 2;
260192595Sdes                length -= 2;
261192595Sdes                caplen -= 2;
262192595Sdes
263221420Sdes                if (ether_type > ETHERMTU) {
264192595Sdes                    if (eflag)
265204917Sdes                        printf("ethertype %s, ",
266192595Sdes                               tok2str(ethertype_values,"0x%04x", ether_type));
267192595Sdes                    goto recurse;
268192595Sdes                }
269295367Sdes
270192595Sdes                *extracted_ether_type = 0;
271192595Sdes
272192595Sdes                if (llc_print(p, length, caplen, p - 16, p - 10,
273192595Sdes                              extracted_ether_type) == 0) {
274192595Sdes                    ether_hdr_print(p - 16, length + 2);
275192595Sdes
276192595Sdes                    if (!suppress_default_print) {
277192595Sdes                            default_print(p - 16, caplen + 2);
278192595Sdes                    }
279192595Sdes                }
280126274Sdes
281126274Sdes                return (1);
282126274Sdes
283126274Sdes        case ETHERTYPE_ISO:
284126274Sdes                isoclns_print(p+1, length-1, length-1);
285126274Sdes                return(1);
286126274Sdes
287126274Sdes	case ETHERTYPE_PPPOED:
288126274Sdes	case ETHERTYPE_PPPOES:
289126274Sdes	case ETHERTYPE_PPPOED2:
290126274Sdes	case ETHERTYPE_PPPOES2:
291126274Sdes		pppoe_print(p, length);
292221420Sdes		return (1);
293126274Sdes
294126274Sdes	case ETHERTYPE_EAPOL:
295126274Sdes	        eap_print(gndo, p, length);
296126274Sdes		return (1);
297126274Sdes
298126274Sdes	case ETHERTYPE_PPP:
299126274Sdes		if (length) {
300126274Sdes			printf(": ");
301126274Sdes			ppp_print(p, length);
302126274Sdes		}
303126274Sdes		return (1);
304126274Sdes
305126274Sdes	case ETHERTYPE_SLOW:
306126274Sdes	        slow_print(p, length);
307126274Sdes		return (1);
308126274Sdes
309126274Sdes        case ETHERTYPE_LOOPBACK:
310126274Sdes                return (1);
311126274Sdes
312126274Sdes	case ETHERTYPE_MPLS:
313126274Sdes	case ETHERTYPE_MPLS_MULTI:
314126274Sdes		mpls_print(p, length);
315162852Sdes		return (1);
316126274Sdes
317126274Sdes	case ETHERTYPE_LAT:
318126274Sdes	case ETHERTYPE_SCA:
319126274Sdes	case ETHERTYPE_MOPRC:
320126274Sdes	case ETHERTYPE_MOPDL:
321126274Sdes		/* default_print for now */
322126274Sdes	default:
323126274Sdes		return (0);
324126274Sdes	}
325126274Sdes}
326126274Sdes
327126274Sdes
328126274Sdes/*
329126274Sdes * Local Variables:
330126274Sdes * c-style: whitesmith
331126274Sdes * c-basic-offset: 8
332255767Sdes * End:
333126274Sdes */
334126274Sdes
335126274Sdes