1 /* $OpenBSD: print-ether.c,v 1.42 2022/06/09 12:56:14 mbuhl Exp $ */
2
3 /*
4 * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997
5 * The Regents of the University of California. All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that: (1) source code distributions
9 * retain the above copyright notice and this paragraph in its entirety, (2)
10 * distributions including binary code include the above copyright notice and
11 * this paragraph in its entirety in the documentation or other materials
12 * provided with the distribution, and (3) all advertising materials mentioning
13 * features or use of this software display the following acknowledgement:
14 * ``This product includes software developed by the University of California,
15 * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
16 * the University nor the names of its contributors may be used to endorse
17 * or promote products derived from this software without specific prior
18 * written permission.
19 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
20 * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
21 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
22 */
23
24 #include <sys/time.h>
25 #include <sys/socket.h>
26
27 #include <net/if.h>
28
29 #include <netinet/in.h>
30 #include <netinet/if_ether.h>
31 #include <netinet/ip.h>
32 #include <netinet/ip6.h>
33 #include <netinet/ip_var.h>
34 #include <netinet/udp.h>
35 #include <netinet/udp_var.h>
36 #include <netinet/tcp.h>
37
38 #include <stdio.h>
39 #include <stddef.h>
40 #include <pcap.h>
41
42
43 #include "interface.h"
44 #include "addrtoname.h"
45 #include "ethertype.h"
46 #include "extract.h"
47
48 const u_char *packetp;
49 const u_char *snapend;
50
51 void ether_macctl(const u_char *, u_int);
52 void ether_pbb_print(const u_char *, u_int, u_int);
53 void ether_eapol_print(const u_char *, u_int, u_int);
54
55 void
ether_print(const u_char * bp,u_int length)56 ether_print(const u_char *bp, u_int length)
57 {
58 const struct ether_header *ep;
59
60 ep = (const struct ether_header *)bp;
61 if (qflag) {
62 TCHECK2(*ep, 12);
63 printf("%s %s %d: ",
64 etheraddr_string(ESRC(ep)),
65 etheraddr_string(EDST(ep)),
66 length);
67 } else {
68 TCHECK2(*ep, 14);
69 printf("%s %s %s %d: ",
70 etheraddr_string(ESRC(ep)),
71 etheraddr_string(EDST(ep)),
72 etherproto_string(ep->ether_type),
73 length);
74 }
75 return;
76 trunc:
77 printf("[|ether] ");
78 }
79
80 u_short extracted_ethertype;
81
82 /*
83 * This is the top level routine of the printer. 'p' is the points
84 * to the ether header of the packet, 'tvp' is the timestamp,
85 * 'length' is the length of the packet off the wire, and 'caplen'
86 * is the number of bytes actually captured.
87 */
88 void
ether_if_print(u_char * user,const struct pcap_pkthdr * h,const u_char * p)89 ether_if_print(u_char *user, const struct pcap_pkthdr *h, const u_char *p)
90 {
91 ts_print(&h->ts);
92
93 /*
94 * Some printers want to get back at the ethernet addresses,
95 * and/or check that they're not walking off the end of the packet.
96 * Rather than pass them all the way down, we set these globals.
97 */
98 snapend = p + h->caplen;
99
100 ether_tryprint(p, h->len, 1);
101 }
102
103 void
ether_tryprint(const u_char * p,u_int length,int first_header)104 ether_tryprint(const u_char *p, u_int length, int first_header)
105 {
106 struct ether_header *ep;
107 u_int caplen = snapend - p;
108 u_short ether_type;
109
110 if (caplen < sizeof(struct ether_header)) {
111 printf("[|ether]");
112 goto out;
113 }
114
115 if (eflag)
116 ether_print(p, length);
117
118 packetp = p;
119 length -= sizeof(struct ether_header);
120 caplen -= sizeof(struct ether_header);
121 ep = (struct ether_header *)p;
122 p += sizeof(struct ether_header);
123
124 ether_type = ntohs(ep->ether_type);
125
126 /*
127 * Is it (gag) an 802.3 encapsulation?
128 */
129 extracted_ethertype = 0;
130 if (ether_type <= ETHERMTU) {
131 /* Try to print the LLC-layer header & higher layers */
132 if (llc_print(p, length, caplen, ESRC(ep), EDST(ep)) == 0) {
133 /* ether_type not known, print raw packet */
134 if (!eflag)
135 ether_print((u_char *)ep, length);
136 if (extracted_ethertype) {
137 printf("(LLC %s) ",
138 etherproto_string(htons(extracted_ethertype)));
139 }
140 if (!xflag && !qflag) {
141 if (eflag)
142 default_print(packetp,
143 snapend - packetp);
144 else
145 default_print(p, caplen);
146 }
147 }
148 } else if (ether_encap_print(ether_type, p, length, caplen) == 0) {
149 /* ether_type not known, print raw packet */
150 if (!eflag)
151 ether_print((u_char *)ep, length + sizeof(*ep));
152 if (!xflag && !qflag) {
153 if (eflag)
154 default_print(packetp, snapend - packetp);
155 else
156 default_print(p, caplen);
157 }
158 }
159 if (xflag && first_header) {
160 if (eflag)
161 default_print(packetp, snapend - packetp);
162 else
163 default_print(p, caplen);
164 }
165 out:
166 if (first_header)
167 putchar('\n');
168 }
169
170 void
ether_pbb_print(const u_char * bp,u_int length,u_int caplen)171 ether_pbb_print(const u_char *bp, u_int length, u_int caplen)
172 {
173 uint32_t itag;
174 uint8_t pri, res;
175
176 if (caplen < sizeof(itag))
177 goto trunc;
178
179 itag = EXTRACT_32BITS(bp);
180
181 bp += sizeof(itag);
182 length -= sizeof(itag);
183 caplen -= sizeof(itag);
184
185 pri = itag >> 29;
186 if (pri <= 1)
187 pri = !pri;
188
189 res = (itag >> 24) & 0x7;
190
191 printf("802.1Q ivid %u pri %u ", itag & 0xffffff, pri);
192 if (itag & (1 << 28))
193 printf("dei ");
194 if (itag & (1 << 27))
195 printf("uca ");
196 if (res)
197 printf("res %u! ", res);
198
199 ether_tryprint(bp, length, 0);
200
201 return;
202
203 trunc:
204 printf("[|pbb] ");
205 }
206
207 /*
208 * Prints the packet encapsulated in an Ethernet data segment
209 * (or an equivalent encapsulation), given the Ethernet type code.
210 *
211 * Returns non-zero if it can do so, zero if the ethertype is unknown.
212 *
213 * Stuffs the ether type into a global for the benefit of lower layers
214 * that might want to know what it is.
215 */
216
217 int
ether_encap_print(u_short ethertype,const u_char * p,u_int length,u_int caplen)218 ether_encap_print(u_short ethertype, const u_char *p,
219 u_int length, u_int caplen)
220 {
221 uint16_t vlan, pri, vid;
222 recurse:
223 extracted_ethertype = ethertype;
224
225 switch (ethertype) {
226
227 case ETHERTYPE_IP:
228 ip_print(p, length);
229 return (1);
230
231 case ETHERTYPE_IPV6:
232 ip6_print(p, length);
233 return (1);
234
235 case ETHERTYPE_ARP:
236 case ETHERTYPE_REVARP:
237 arp_print(p, length, caplen);
238 return (1);
239
240 case ETHERTYPE_DN:
241 decnet_print(p, length, caplen);
242 return (1);
243
244 case ETHERTYPE_ATALK:
245 if (vflag)
246 printf("et1 ");
247 atalk_print_llap(p, length);
248 return (1);
249
250 case ETHERTYPE_AARP:
251 aarp_print(p, length);
252 return (1);
253
254 case ETHERTYPE_8021Q:
255 printf("802.1Q ");
256 case ETHERTYPE_QINQ:
257 if (ethertype == ETHERTYPE_QINQ)
258 printf("QinQ s");
259
260 /* XXX caplen check */
261
262 vlan = ntohs(*(unsigned short*)p);
263 vid = vlan & 0xfff;
264 pri = vlan >> 13;
265 if (pri <= 1)
266 pri = !pri;
267
268 printf("vid %d pri %d%s", vid, pri,
269 vlan & 0x1000 ? " dei " : " ");
270 ethertype = ntohs(*(unsigned short*)(p+2));
271 p += 4;
272 length -= 4;
273 caplen -= 4;
274 if (ethertype > ETHERMTU)
275 goto recurse;
276
277 extracted_ethertype = 0;
278
279 if (llc_print(p, length, caplen, p-18, p-12) == 0) {
280 /* ether_type not known, print raw packet */
281 if (!eflag)
282 ether_print(p-18, length+4);
283 if (extracted_ethertype) {
284 printf("(LLC %s) ",
285 etherproto_string(htons(extracted_ethertype)));
286 }
287 if (!xflag && !qflag)
288 default_print(p-18, caplen+4);
289 }
290 return (1);
291
292 case ETHERTYPE_NSH:
293 nsh_print(p, length);
294 return (1);
295
296 case ETHERTYPE_EAPOL:
297 ether_eapol_print(p, length, caplen);
298 return (1);
299
300 case ETHERTYPE_PBB:
301 ether_pbb_print(p, length, caplen);
302 return (1);
303
304 case ETHERTYPE_NHRP:
305 nhrp_print(p, length);
306 return (1);
307
308 #ifdef PPP
309 case ETHERTYPE_PPPOEDISC:
310 case ETHERTYPE_PPPOE:
311 pppoe_if_print(ethertype, p, length, caplen);
312 return (1);
313 #endif
314
315 case ETHERTYPE_FLOWCONTROL:
316 ether_macctl(p, length);
317 return (1);
318
319 case ETHERTYPE_MPLS:
320 case ETHERTYPE_MPLS_MCAST:
321 mpls_print(p, length);
322 return (1);
323
324 case ETHERTYPE_LLDP:
325 lldp_print(p, length);
326 return (1);
327
328 case ETHERTYPE_SLOW:
329 slow_print(p, length);
330 return (1);
331
332 case ETHERTYPE_LAT:
333 case ETHERTYPE_SCA:
334 case ETHERTYPE_MOPRC:
335 case ETHERTYPE_MOPDL:
336 /* default_print for now */
337 default:
338 return (0);
339 }
340 }
341
342 void
ether_macctl(const u_char * p,u_int length)343 ether_macctl(const u_char *p, u_int length)
344 {
345 printf("MACCTL");
346
347 if (length < 2)
348 goto trunc;
349 if (EXTRACT_16BITS(p) == 0x0001) {
350 u_int plen;
351
352 printf(" PAUSE");
353
354 length -= 2;
355 p += 2;
356 if (length < 2)
357 goto trunc;
358 plen = 512 * EXTRACT_16BITS(p);
359 printf(" quanta %u", plen);
360 } else {
361 printf(" unknown-opcode(0x%04x)", EXTRACT_16BITS(p));
362 }
363 return;
364
365 trunc:
366 printf("[|MACCTL]");
367 }
368
369 /*
370 * 802.1X EAPOL PDU
371 */
372
373 struct eapol_header {
374 uint8_t version;
375 uint8_t type;
376 #define EAPOL_T_EAP 0x00
377 #define EAPOL_T_START 0x01
378 #define EAPOL_T_LOGOFF 0x02
379 #define EAPOL_T_KEY 0x03
380 #define EAPOL_T_ENCAP_ASF_ALERT 0x04
381 #define EAPOL_T_MKA 0x05
382 #define EAPOL_T_ANNOUNCEMENT_GENERIC 0x06
383 #define EAPOL_T_ANNOUNCEMENT_SPECIFIC 0x07
384 #define EAPOL_T_ANNOUNCEMENT_REQ 0x08
385 uint16_t length;
386 };
387
388 void
ether_eapol_print(const u_char * bp,u_int length,u_int caplen)389 ether_eapol_print(const u_char *bp, u_int length, u_int caplen)
390 {
391 struct eapol_header h;
392
393 printf("EAPOL");
394
395 if (caplen < sizeof(h))
396 goto trunc;
397
398 h.version = *(bp + offsetof(struct eapol_header, version));
399 h.type = *(bp + offsetof(struct eapol_header, type));
400 h.length = EXTRACT_16BITS(bp + offsetof(struct eapol_header, length));
401
402 bp += sizeof(h);
403 length -= sizeof(h);
404 caplen -= sizeof(h);
405
406 if (vflag)
407 printf(" (v%u, len %u)", h.version, h.length);
408
409 if (length > h.length)
410 length = h.length;
411 else if (length < h.length) {
412 printf(" truncated-eapol - %u bytes missing!",
413 h.length - length);
414 }
415
416 switch (h.type) {
417 case EAPOL_T_EAP:
418 printf(" EAP");
419 break;
420 case EAPOL_T_START:
421 printf(" Start");
422 break;
423 case EAPOL_T_LOGOFF:
424 printf(" Logoff");
425 break;
426 case EAPOL_T_KEY:
427 printf(" Key");
428 break;
429 case EAPOL_T_MKA:
430 printf(" MKA");
431 break;
432 case EAPOL_T_ANNOUNCEMENT_GENERIC:
433 printf(" Announcement (Generic)");
434 break;
435 case EAPOL_T_ANNOUNCEMENT_SPECIFIC:
436 printf(" Announcement (Specific)");
437 break;
438 case EAPOL_T_ANNOUNCEMENT_REQ:
439 printf(" Announcement Req");
440 break;
441 default:
442 printf(" unknown (%u)", h.type);
443 break;
444 }
445
446 return;
447
448 trunc:
449 printf(" [|eapol] ");
450 }
451