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 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 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 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 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 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 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 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