1 /* $OpenBSD: print-ether.c,v 1.19 2004/01/22 16:18:52 jason 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 #ifndef lint 24 static const char rcsid[] = 25 "@(#) $Header: /home/cvs/src/usr.sbin/tcpdump/print-ether.c,v 1.19 2004/01/22 16:18:52 jason Exp $ (LBL)"; 26 #endif 27 28 #include <sys/param.h> 29 #include <sys/time.h> 30 #include <sys/socket.h> 31 32 struct mbuf; 33 struct rtentry; 34 #include <net/if.h> 35 36 #include <netinet/in.h> 37 #include <netinet/if_ether.h> 38 #include <netinet/in_systm.h> 39 #include <netinet/ip.h> 40 #include <netinet/ip_var.h> 41 #include <netinet/udp.h> 42 #include <netinet/udp_var.h> 43 #include <netinet/tcp.h> 44 45 #include <stdio.h> 46 #include <pcap.h> 47 48 #ifdef INET6 49 #include <netinet/ip6.h> 50 #endif 51 52 #include "interface.h" 53 #include "addrtoname.h" 54 #include "ethertype.h" 55 #include "extract.h" 56 57 const u_char *packetp; 58 const u_char *snapend; 59 60 void ether_macctl(const u_char *, u_int); 61 62 void 63 ether_print(register const u_char *bp, u_int length) 64 { 65 register const struct ether_header *ep; 66 67 ep = (const struct ether_header *)bp; 68 if (qflag) 69 (void)printf("%s %s %d: ", 70 etheraddr_string(ESRC(ep)), 71 etheraddr_string(EDST(ep)), 72 length); 73 else 74 (void)printf("%s %s %s %d: ", 75 etheraddr_string(ESRC(ep)), 76 etheraddr_string(EDST(ep)), 77 etherproto_string(ep->ether_type), 78 length); 79 } 80 81 u_short extracted_ethertype; 82 83 /* 84 * This is the top level routine of the printer. 'p' is the points 85 * to the ether header of the packet, 'tvp' is the timestamp, 86 * 'length' is the length of the packet off the wire, and 'caplen' 87 * is the number of bytes actually captured. 88 */ 89 void 90 ether_if_print(u_char *user, const struct pcap_pkthdr *h, const u_char *p) 91 { 92 u_int caplen = h->caplen; 93 u_int length = h->len; 94 struct ether_header *ep; 95 u_short ether_type; 96 97 ts_print(&h->ts); 98 99 if (caplen < sizeof(struct ether_header)) { 100 printf("[|ether]"); 101 goto out; 102 } 103 104 if (eflag) 105 ether_print(p, length); 106 107 /* 108 * Some printers want to get back at the ethernet addresses, 109 * and/or check that they're not walking off the end of the packet. 110 * Rather than pass them all the way down, we set these globals. 111 */ 112 packetp = p; 113 snapend = p + caplen; 114 115 length -= sizeof(struct ether_header); 116 caplen -= sizeof(struct ether_header); 117 ep = (struct ether_header *)p; 118 p += sizeof(struct ether_header); 119 120 ether_type = ntohs(ep->ether_type); 121 122 /* 123 * Is it (gag) an 802.3 encapsulation? 124 */ 125 extracted_ethertype = 0; 126 if (ether_type <= ETHERMTU) { 127 /* Try to print the LLC-layer header & higher layers */ 128 if (llc_print(p, length, caplen, ESRC(ep), EDST(ep)) == 0) { 129 /* ether_type not known, print raw packet */ 130 if (!eflag) 131 ether_print((u_char *)ep, length); 132 if (extracted_ethertype) { 133 printf("(LLC %s) ", 134 etherproto_string(htons(extracted_ethertype))); 135 } 136 if (!xflag && !qflag) 137 default_print(p, caplen); 138 } 139 } else if (ether_encap_print(ether_type, p, length, caplen) == 0) { 140 /* ether_type not known, print raw packet */ 141 if (!eflag) 142 ether_print((u_char *)ep, length + sizeof(*ep)); 143 if (!xflag && !qflag) 144 default_print(p, caplen); 145 } 146 if (xflag) 147 default_print(p, caplen); 148 out: 149 putchar('\n'); 150 } 151 152 /* 153 * Prints the packet encapsulated in an Ethernet data segment 154 * (or an equivalent encapsulation), given the Ethernet type code. 155 * 156 * Returns non-zero if it can do so, zero if the ethertype is unknown. 157 * 158 * Stuffs the ether type into a global for the benefit of lower layers 159 * that might want to know what it is. 160 */ 161 162 int 163 ether_encap_print(u_short ethertype, const u_char *p, 164 u_int length, u_int caplen) 165 { 166 recurse: 167 extracted_ethertype = ethertype; 168 169 switch (ethertype) { 170 171 case ETHERTYPE_IP: 172 ip_print(p, length); 173 return (1); 174 175 #ifdef INET6 176 case ETHERTYPE_IPV6: 177 ip6_print(p, length); 178 return (1); 179 #endif /*INET6*/ 180 181 case ETHERTYPE_ARP: 182 case ETHERTYPE_REVARP: 183 arp_print(p, length, caplen); 184 return (1); 185 186 case ETHERTYPE_DN: 187 decnet_print(p, length, caplen); 188 return (1); 189 190 case ETHERTYPE_ATALK: 191 if (vflag) 192 fputs("et1 ", stdout); 193 atalk_print_llap(p, length); 194 return (1); 195 196 case ETHERTYPE_AARP: 197 aarp_print(p, length); 198 return (1); 199 200 case ETHERTYPE_8021Q: 201 printf("802.1Q vid %d pri %d%s", 202 ntohs(*(unsigned short*)p)&0xFFF, 203 ntohs(*(unsigned short*)p)>>13, 204 (ntohs(*(unsigned short*)p)&0x1000) ? " cfi " : " "); 205 ethertype = ntohs(*(unsigned short*)(p+2)); 206 p += 4; 207 length -= 4; 208 caplen -= 4; 209 if (ethertype > ETHERMTU) 210 goto recurse; 211 212 extracted_ethertype = 0; 213 214 if (llc_print(p, length, caplen, p-18, p-12) == 0) { 215 /* ether_type not known, print raw packet */ 216 if (!eflag) 217 ether_print(p-18, length+4); 218 if (extracted_ethertype) { 219 printf("(LLC %s) ", 220 etherproto_string(htons(extracted_ethertype))); 221 } 222 if (!xflag && !qflag) 223 default_print(p-18, caplen+4); 224 } 225 return (1); 226 227 #ifdef PPP 228 case ETHERTYPE_PPPOEDISC: 229 case ETHERTYPE_PPPOE: 230 pppoe_if_print(ethertype, p, length, caplen); 231 return (1); 232 #endif 233 234 case ETHERTYPE_FLOWCONTROL: 235 ether_macctl(p, length); 236 return (1); 237 238 case ETHERTYPE_LAT: 239 case ETHERTYPE_SCA: 240 case ETHERTYPE_MOPRC: 241 case ETHERTYPE_MOPDL: 242 /* default_print for now */ 243 default: 244 return (0); 245 } 246 } 247 248 void 249 ether_macctl(const u_char *p, u_int length) 250 { 251 printf("MACCTL"); 252 253 if (length < 2) 254 goto trunc; 255 if (EXTRACT_16BITS(p) == 0x0001) { 256 u_int plen; 257 258 printf(" PAUSE"); 259 260 length -= 2; 261 p += 2; 262 if (length < 2) 263 goto trunc; 264 plen = 512 * EXTRACT_16BITS(p); 265 printf(" quanta %u", plen); 266 } else { 267 printf(" unknown-opcode(0x%04x)", EXTRACT_16BITS(p)); 268 } 269 return; 270 271 trunc: 272 printf("[|MACCTL]"); 273 } 274