Home | History | Annotate | Download | only in tcpdump
      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.95.2.6 2006/02/20 18:15:03 hannes 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_SLOW,           "Slow Protocols" },
     69     { ETHERTYPE_PPPOED,         "PPPoE D" },
     70     { ETHERTYPE_PPPOES,         "PPPoE S" },
     71     { ETHERTYPE_EAPOL,          "EAPOL" },
     72     { ETHERTYPE_JUMBO,          "Jumbo" },
     73     { ETHERTYPE_LOOPBACK,       "Loopback" },
     74     { ETHERTYPE_ISO,            "OSI" },
     75     { ETHERTYPE_GRE_ISO,        "GRE-OSI" },
     76     { 0, NULL}
     77 };
     78 
     79 static inline void
     80 ether_hdr_print(register const u_char *bp, u_int length)
     81 {
     82 	register const struct ether_header *ep;
     83 	ep = (const struct ether_header *)bp;
     84 
     85 	(void)printf("%s > %s",
     86 		     etheraddr_string(ESRC(ep)),
     87 		     etheraddr_string(EDST(ep)));
     88 
     89 	if (!qflag) {
     90 	        if (ntohs(ep->ether_type) <= ETHERMTU)
     91 		          (void)printf(", 802.3");
     92                 else
     93 		          (void)printf(", ethertype %s (0x%04x)",
     94 				       tok2str(ethertype_values,"Unknown", ntohs(ep->ether_type)),
     95                                        ntohs(ep->ether_type));
     96         } else {
     97                 if (ntohs(ep->ether_type) <= ETHERMTU)
     98                           (void)printf(", 802.3");
     99                 else
    100                           (void)printf(", %s", tok2str(ethertype_values,"Unknown Ethertype (0x%04x)", ntohs(ep->ether_type)));
    101         }
    102 
    103 	(void)printf(", length %u: ", length);
    104 }
    105 
    106 void
    107 ether_print(const u_char *p, u_int length, u_int caplen)
    108 {
    109 	struct ether_header *ep;
    110 	u_short ether_type;
    111 	u_short extracted_ether_type;
    112 
    113 	if (caplen < ETHER_HDRLEN) {
    114 		printf("[|ether]");
    115 		return;
    116 	}
    117 
    118 	if (eflag)
    119 		ether_hdr_print(p, length);
    120 
    121 	length -= ETHER_HDRLEN;
    122 	caplen -= ETHER_HDRLEN;
    123 	ep = (struct ether_header *)p;
    124 	p += ETHER_HDRLEN;
    125 
    126 	ether_type = ntohs(ep->ether_type);
    127 
    128 	/*
    129 	 * Is it (gag) an 802.3 encapsulation?
    130 	 */
    131 	if (ether_type <= ETHERMTU) {
    132 		/* Try to print the LLC-layer header & higher layers */
    133 		if (llc_print(p, length, caplen, ESRC(ep), EDST(ep),
    134 		    &extracted_ether_type) == 0) {
    135 			/* ether_type not known, print raw packet */
    136 			if (!eflag)
    137 				ether_hdr_print((u_char *)ep, length + ETHER_HDRLEN);
    138 
    139 			if (!suppress_default_print)
    140 				default_print(p, caplen);
    141 		}
    142 	} else if (ether_encap_print(ether_type, p, length, caplen,
    143 	    &extracted_ether_type) == 0) {
    144 		/* ether_type not known, print raw packet */
    145 		if (!eflag)
    146 			ether_hdr_print((u_char *)ep, length + ETHER_HDRLEN);
    147 
    148 		if (!suppress_default_print)
    149 			default_print(p, caplen);
    150 	}
    151 }
    152 
    153 /*
    154  * This is the top level routine of the printer.  'p' points
    155  * to the ether header of the packet, 'h->ts' is the timestamp,
    156  * 'h->len' is the length of the packet off the wire, and 'h->caplen'
    157  * is the number of bytes actually captured.
    158  */
    159 u_int
    160 ether_if_print(const struct pcap_pkthdr *h, const u_char *p)
    161 {
    162 	ether_print(p, h->len, h->caplen);
    163 
    164 	return (ETHER_HDRLEN);
    165 }
    166 
    167 /*
    168  * Prints the packet encapsulated in an Ethernet data segment
    169  * (or an equivalent encapsulation), given the Ethernet type code.
    170  *
    171  * Returns non-zero if it can do so, zero if the ethertype is unknown.
    172  *
    173  * The Ethernet type code is passed through a pointer; if it was
    174  * ETHERTYPE_8021Q, it gets updated to be the Ethernet type of
    175  * the 802.1Q payload, for the benefit of lower layers that might
    176  * want to know what it is.
    177  */
    178 
    179 int
    180 ether_encap_print(u_short ether_type, const u_char *p,
    181     u_int length, u_int caplen, u_short *extracted_ether_type)
    182 {
    183  recurse:
    184 	*extracted_ether_type = ether_type;
    185 
    186 	switch (ether_type) {
    187 
    188 	case ETHERTYPE_IP:
    189 	        ip_print(gndo, p, length);
    190 		return (1);
    191 
    192 #ifdef INET6
    193 	case ETHERTYPE_IPV6:
    194 		ip6_print(p, length);
    195 		return (1);
    196 #endif /*INET6*/
    197 
    198 	case ETHERTYPE_ARP:
    199 	case ETHERTYPE_REVARP:
    200   	        arp_print(gndo, p, length, caplen);
    201 		return (1);
    202 
    203 	case ETHERTYPE_DN:
    204 		decnet_print(p, length, caplen);
    205 		return (1);
    206 
    207 	case ETHERTYPE_ATALK:
    208 		if (vflag)
    209 			fputs("et1 ", stdout);
    210 		atalk_print(p, length);
    211 		return (1);
    212 
    213 	case ETHERTYPE_AARP:
    214 		aarp_print(p, length);
    215 		return (1);
    216 
    217 	case ETHERTYPE_IPX:
    218 		printf("(NOV-ETHII) ");
    219 		ipx_print(p, length);
    220 		return (1);
    221 
    222 	case ETHERTYPE_8021Q:
    223 	        if (eflag)
    224 		    printf("vlan %u, p %u%s, ",
    225 			   ntohs(*(u_int16_t *)p) & 0xfff,
    226 			   ntohs(*(u_int16_t *)p) >> 13,
    227 			   (ntohs(*(u_int16_t *)p) & 0x1000) ? ", CFI" : "");
    228 
    229 		ether_type = ntohs(*(u_int16_t *)(p + 2));
    230 		p += 4;
    231 		length -= 4;
    232 		caplen -= 4;
    233 
    234 		if (ether_type > ETHERMTU) {
    235 		        if (eflag)
    236 			        printf("ethertype %s, ",
    237 				       tok2str(ethertype_values,"0x%04x", ether_type));
    238 			goto recurse;
    239 		}
    240 
    241 		*extracted_ether_type = 0;
    242 
    243 		if (llc_print(p, length, caplen, p - 18, p - 12,
    244 		    extracted_ether_type) == 0) {
    245                         ether_hdr_print(p - 18, length + 4);
    246 
    247                         if (!suppress_default_print) {
    248                                 default_print(p - 18, caplen + 4);
    249                         }
    250 		}
    251 
    252 
    253 		return (1);
    254 
    255         case ETHERTYPE_JUMBO:
    256                 ether_type = ntohs(*(u_int16_t *)(p));
    257                 p += 2;
    258                 length -= 2;
    259                 caplen -= 2;
    260 
    261                 if (ether_type > ETHERMTU) {
    262                     if (eflag)
    263                         printf("ethertype %s, ",
    264                                tok2str(ethertype_values,"0x%04x", ether_type));
    265                     goto recurse;
    266                 }
    267 
    268                 *extracted_ether_type = 0;
    269 
    270                 if (llc_print(p, length, caplen, p - 16, p - 10,
    271                               extracted_ether_type) == 0) {
    272                     ether_hdr_print(p - 16, length + 2);
    273 
    274                     if (!suppress_default_print) {
    275                             default_print(p - 16, caplen + 2);
    276                     }
    277                 }
    278 
    279                 return (1);
    280 
    281         case ETHERTYPE_ISO:
    282                 isoclns_print(p+1, length-1, length-1);
    283                 return(1);
    284 
    285 	case ETHERTYPE_PPPOED:
    286 	case ETHERTYPE_PPPOES:
    287 		pppoe_print(p, length);
    288 		return (1);
    289 
    290 	case ETHERTYPE_EAPOL:
    291 	        eap_print(gndo, p, length);
    292 		return (1);
    293 
    294 	case ETHERTYPE_PPP:
    295 		if (length) {
    296 			printf(": ");
    297 			ppp_print(p, length);
    298 		}
    299 		return (1);
    300 
    301 	case ETHERTYPE_SLOW:
    302 	        slow_print(p, length);
    303 		return (1);
    304 
    305         case ETHERTYPE_LOOPBACK:
    306                 return (1);
    307 
    308 	case ETHERTYPE_MPLS:
    309 	case ETHERTYPE_MPLS_MULTI:
    310 		mpls_print(p, length);
    311 		return (1);
    312 
    313 	case ETHERTYPE_LAT:
    314 	case ETHERTYPE_SCA:
    315 	case ETHERTYPE_MOPRC:
    316 	case ETHERTYPE_MOPDL:
    317 		/* default_print for now */
    318 	default:
    319 		return (0);
    320 	}
    321 }
    322 
    323 
    324 /*
    325  * Local Variables:
    326  * c-style: whitesmith
    327  * c-basic-offset: 8
    328  * End:
    329  */
    330 
    331