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