print-ether.c revision 84019
1233294Sstas/*
2178825Sdfr * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997
3178825Sdfr *	The Regents of the University of California.  All rights reserved.
4178825Sdfr *
5178825Sdfr * Redistribution and use in source and binary forms, with or without
6178825Sdfr * modification, are permitted provided that: (1) source code distributions
7178825Sdfr * retain the above copyright notice and this paragraph in its entirety, (2)
8233294Sstas * distributions including binary code include the above copyright notice and
9178825Sdfr * this paragraph in its entirety in the documentation or other materials
10178825Sdfr * provided with the distribution, and (3) all advertising materials mentioning
11178825Sdfr * features or use of this software display the following acknowledgement:
12178825Sdfr * ``This product includes software developed by the University of California,
13233294Sstas * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
14178825Sdfr * the University nor the names of its contributors may be used to endorse
15178825Sdfr * or promote products derived from this software without specific prior
16178825Sdfr * written permission.
17178825Sdfr * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
18178825Sdfr * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
19178825Sdfr * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
20178825Sdfr *
21178825Sdfr * $FreeBSD: head/contrib/tcpdump/print-ether.c 84019 2001-09-27 08:02:27Z julian $
22178825Sdfr */
23178825Sdfr#ifndef lint
24178825Sdfrstatic const char rcsid[] =
25178825Sdfr    "@(#) $Header: /tcpdump/master/tcpdump/print-ether.c,v 1.61 2000/12/22 22:45:10 guy Exp $ (LBL)";
26178825Sdfr#endif
27178825Sdfr
28178825Sdfr#ifdef HAVE_CONFIG_H
29178825Sdfr#include "config.h"
30178825Sdfr#endif
31178825Sdfr
32178825Sdfr#include <sys/param.h>
33178825Sdfr#include <sys/time.h>
34178825Sdfr#include <sys/socket.h>
35178825Sdfr
36178825Sdfrstruct mbuf;
37178825Sdfrstruct rtentry;
38233294Sstas
39178825Sdfr#include <netinet/in.h>
40178825Sdfr
41178825Sdfr#include <stdio.h>
42178825Sdfr#include <pcap.h>
43178825Sdfr
44178825Sdfr#include "interface.h"
45178825Sdfr#include "addrtoname.h"
46178825Sdfr#include "ethertype.h"
47178825Sdfr
48178825Sdfr#include "ether.h"
49178825Sdfr
50178825Sdfrconst u_char *packetp;
51178825Sdfrconst u_char *snapend;
52178825Sdfr
53178825Sdfrstatic inline void
54178825Sdfrether_print(register const u_char *bp, u_int length)
55178825Sdfr{
56178825Sdfr	register const struct ether_header *ep;
57178825Sdfr
58178825Sdfr	ep = (const struct ether_header *)bp;
59178825Sdfr	if (qflag)
60178825Sdfr		(void)printf("%s %s %d: ",
61178825Sdfr			     etheraddr_string(ESRC(ep)),
62178825Sdfr			     etheraddr_string(EDST(ep)),
63178825Sdfr			     length);
64178825Sdfr	else
65178825Sdfr		(void)printf("%s %s %s %d: ",
66178825Sdfr			     etheraddr_string(ESRC(ep)),
67178825Sdfr			     etheraddr_string(EDST(ep)),
68178825Sdfr			     etherproto_string(ep->ether_type),
69233294Sstas			     length);
70178825Sdfr}
71233294Sstas
72178825Sdfr/*
73233294Sstas * This is the top level routine of the printer.  'p' is the points
74178825Sdfr * to the ether header of the packet, 'h->tv' is the timestamp,
75178825Sdfr * 'h->length' is the length of the packet off the wire, and 'h->caplen'
76178825Sdfr * is the number of bytes actually captured.
77178825Sdfr */
78178825Sdfrvoid
79178825Sdfrether_if_print(u_char *user, const struct pcap_pkthdr *h, const u_char *p)
80178825Sdfr{
81233294Sstas	u_int caplen = h->caplen;
82178825Sdfr	u_int length = h->len;
83178825Sdfr	struct ether_header *ep;
84178825Sdfr	u_short ether_type;
85178825Sdfr	u_short extracted_ethertype;
86233294Sstas
87178825Sdfr	ts_print(&h->ts);
88178825Sdfr
89178825Sdfr	if (caplen < ETHER_HDRLEN) {
90178825Sdfr		printf("[|ether]");
91178825Sdfr		goto out;
92178825Sdfr	}
93178825Sdfr
94233294Sstas	if (eflag)
95178825Sdfr		ether_print(p, length);
96178825Sdfr
97178825Sdfr	/*
98178825Sdfr	 * Some printers want to get back at the ethernet addresses,
99178825Sdfr	 * and/or check that they're not walking off the end of the packet.
100178825Sdfr	 * Rather than pass them all the way down, we set these globals.
101178825Sdfr	 */
102178825Sdfr	packetp = p;
103178825Sdfr	snapend = p + caplen;
104178825Sdfr
105178825Sdfr	length -= ETHER_HDRLEN;
106178825Sdfr	caplen -= ETHER_HDRLEN;
107178825Sdfr	ep = (struct ether_header *)p;
108233294Sstas	p += ETHER_HDRLEN;
109178825Sdfr
110233294Sstas	ether_type = ntohs(ep->ether_type);
111178825Sdfr
112178825Sdfr	/*
113178825Sdfr	 * Is it (gag) an 802.3 encapsulation?
114178825Sdfr	 */
115178825Sdfr	extracted_ethertype = 0;
116178825Sdfr	if (ether_type <= ETHERMTU) {
117178825Sdfr		/* Try to print the LLC-layer header & higher layers */
118178825Sdfr		if (llc_print(p, length, caplen, ESRC(ep), EDST(ep),
119178825Sdfr		    &extracted_ethertype) == 0) {
120233294Sstas			/* ether_type not known, print raw packet */
121178825Sdfr			if (!eflag)
122178825Sdfr				ether_print((u_char *)ep, length + ETHER_HDRLEN);
123178825Sdfr			if (extracted_ethertype) {
124178825Sdfr				printf("(LLC %s) ",
125178825Sdfr			       etherproto_string(htons(extracted_ethertype)));
126178825Sdfr			}
127178825Sdfr			if (!xflag && !qflag)
128178825Sdfr				default_print(p, caplen);
129178825Sdfr		}
130178825Sdfr	} else if (ether_encap_print(ether_type, p, length, caplen,
131178825Sdfr	    &extracted_ethertype) == 0) {
132178825Sdfr		/* ether_type not known, print raw packet */
133178825Sdfr		if (!eflag)
134233294Sstas			ether_print((u_char *)ep, length + ETHER_HDRLEN);
135178825Sdfr		if (!xflag && !qflag)
136178825Sdfr			default_print(p, caplen);
137178825Sdfr	}
138178825Sdfr	if (xflag)
139178825Sdfr		default_print(p, caplen);
140178825Sdfr out:
141178825Sdfr	putchar('\n');
142178825Sdfr}
143178825Sdfr
144178825Sdfr/*
145178825Sdfr * Prints the packet encapsulated in an Ethernet data segment
146178825Sdfr * (or an equivalent encapsulation), given the Ethernet type code.
147178825Sdfr *
148178825Sdfr * Returns non-zero if it can do so, zero if the ethertype is unknown.
149178825Sdfr *
150178825Sdfr * The Ethernet type code is passed through a pointer; if it was
151178825Sdfr * ETHERTYPE_8021Q, it gets updated to be the Ethernet type of
152178825Sdfr * the 802.1Q payload, for the benefit of lower layers that might
153178825Sdfr * want to know what it is.
154178825Sdfr */
155178825Sdfr
156178825Sdfrint
157178825Sdfrether_encap_print(u_short ethertype, const u_char *p,
158178825Sdfr    u_int length, u_int caplen, u_short *extracted_ethertype)
159178825Sdfr{
160178825Sdfr recurse:
161178825Sdfr	*extracted_ethertype = ethertype;
162178825Sdfr
163178825Sdfr	switch (ethertype) {
164178825Sdfr
165233294Sstas	case ETHERTYPE_IP:
166178825Sdfr		ip_print(p, length);
167178825Sdfr		return (1);
168178825Sdfr
169178825Sdfr#ifdef INET6
170178825Sdfr	case ETHERTYPE_IPV6:
171178825Sdfr		ip6_print(p, length);
172178825Sdfr		return (1);
173233294Sstas#endif /*INET6*/
174178825Sdfr
175178825Sdfr	case ETHERTYPE_ARP:
176178825Sdfr	case ETHERTYPE_REVARP:
177233294Sstas		arp_print(p, length, caplen);
178178825Sdfr		return (1);
179178825Sdfr
180178825Sdfr	case ETHERTYPE_DN:
181178825Sdfr		decnet_print(p, length, caplen);
182178825Sdfr		return (1);
183178825Sdfr
184233294Sstas	case ETHERTYPE_ATALK:
185178825Sdfr		if (vflag)
186178825Sdfr			fputs("et1 ", stdout);
187178825Sdfr		atalk_print(p, length);
188178825Sdfr		return (1);
189233294Sstas
190178825Sdfr	case ETHERTYPE_AARP:
191178825Sdfr		aarp_print(p, length);
192178825Sdfr		return (1);
193233294Sstas
194178825Sdfr	case ETHERTYPE_IPX:
195178825Sdfr		ipx_print(p, length);
196178825Sdfr		return (1);
197233294Sstas
198178825Sdfr	case ETHERTYPE_8021Q:
199178825Sdfr		printf("802.1Q vlan#%d P%d%s ",
200178825Sdfr		       ntohs(*(u_int16_t *)p) & 0xfff,
201233294Sstas		       ntohs(*(u_int16_t *)p) >> 13,
202178825Sdfr		       (ntohs(*(u_int16_t *)p) & 0x1000) ? " CFI" : "");
203178825Sdfr		ethertype = ntohs(*(u_int16_t *)(p + 2));
204178825Sdfr		p += 4;
205178825Sdfr		length -= 4;
206178825Sdfr		caplen -= 4;
207233294Sstas		if (ethertype > ETHERMTU)
208178825Sdfr			goto recurse;
209178825Sdfr
210178825Sdfr		*extracted_ethertype = 0;
211178825Sdfr
212178825Sdfr		if (llc_print(p, length, caplen, p - 18, p - 12,
213178825Sdfr		    extracted_ethertype) == 0) {
214178825Sdfr			/* ether_type not known, print raw packet */
215233294Sstas			if (!eflag)
216178825Sdfr				ether_print(p - 18, length + 4);
217178825Sdfr			if (*extracted_ethertype) {
218178825Sdfr				printf("(LLC %s) ",
219233294Sstas			       etherproto_string(htons(*extracted_ethertype)));
220178825Sdfr			}
221233294Sstas			if (!xflag && !qflag)
222178825Sdfr				default_print(p - 18, caplen + 4);
223178825Sdfr		}
224178825Sdfr		return (1);
225178825Sdfr
226178825Sdfr	case ETHERTYPE_PPPOED:
227178825Sdfr	case ETHERTYPE_PPPOES:
228178825Sdfr	case ETHERTYPE_PPPOED2:
229178825Sdfr	case ETHERTYPE_PPPOES2:
230178825Sdfr		pppoe_print(p, length);
231178825Sdfr 		return (1);
232178825Sdfr
233178825Sdfr	case ETHERTYPE_LAT:
234233294Sstas	case ETHERTYPE_SCA:
235178825Sdfr	case ETHERTYPE_MOPRC:
236178825Sdfr	case ETHERTYPE_MOPDL:
237178825Sdfr		/* default_print for now */
238178825Sdfr	default:
239233294Sstas		return (0);
240178825Sdfr	}
241178825Sdfr}
242178825Sdfr