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