175115Sfenner/* 275115Sfenner * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997 375115Sfenner * The Regents of the University of California. All rights reserved. 475115Sfenner * 575115Sfenner * Redistribution and use in source and binary forms, with or without 675115Sfenner * modification, are permitted provided that: (1) source code distributions 775115Sfenner * retain the above copyright notice and this paragraph in its entirety, (2) 875115Sfenner * distributions including binary code include the above copyright notice and 975115Sfenner * this paragraph in its entirety in the documentation or other materials 1075115Sfenner * provided with the distribution, and (3) all advertising materials mentioning 1175115Sfenner * features or use of this software display the following acknowledgement: 1275115Sfenner * ``This product includes software developed by the University of California, 1375115Sfenner * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of 1475115Sfenner * the University nor the names of its contributors may be used to endorse 1575115Sfenner * or promote products derived from this software without specific prior 1675115Sfenner * written permission. 1775115Sfenner * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED 1875115Sfenner * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF 1975115Sfenner * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 2075115Sfenner */ 2175115Sfenner#ifndef lint 22127668Sbmsstatic const char rcsid[] _U_ = 23190207Srpaulo "@(#) $Header: /tcpdump/master/tcpdump/print-sll.c,v 1.19 2005-11-13 12:12:43 guy Exp $ (LBL)"; 2475115Sfenner#endif 2575115Sfenner 2675115Sfenner#ifdef HAVE_CONFIG_H 2775115Sfenner#include "config.h" 2875115Sfenner#endif 2975115Sfenner 30127668Sbms#include <tcpdump-stdinc.h> 3175115Sfenner 3275115Sfenner#include <stdio.h> 3375115Sfenner#include <string.h> 3475115Sfenner#include <pcap.h> 3575115Sfenner 3675115Sfenner#include "interface.h" 3775115Sfenner#include "addrtoname.h" 3875115Sfenner#include "ethertype.h" 39146773Ssam#include "extract.h" 4075115Sfenner 4175115Sfenner#include "ether.h" 4275115Sfenner#include "sll.h" 4375115Sfenner 44146773Ssamconst struct tok sll_pkttype_values[] = { 45146773Ssam { LINUX_SLL_HOST, "In" }, 46146773Ssam { LINUX_SLL_BROADCAST, "B" }, 47146773Ssam { LINUX_SLL_MULTICAST, "M" }, 48146773Ssam { LINUX_SLL_OTHERHOST, "P" }, 49146773Ssam { LINUX_SLL_OUTGOING, "Out" }, 50146773Ssam { 0, NULL} 51146773Ssam}; 52146773Ssam 5375115Sfennerstatic inline void 5475115Sfennersll_print(register const struct sll_header *sllp, u_int length) 5575115Sfenner{ 56147899Ssam u_short ether_type; 57147899Ssam 58146773Ssam printf("%3s ",tok2str(sll_pkttype_values,"?",EXTRACT_16BITS(&sllp->sll_pkttype))); 5975115Sfenner 6075115Sfenner /* 6175115Sfenner * XXX - check the link-layer address type value? 6275115Sfenner * For now, we just assume 6 means Ethernet. 6375115Sfenner * XXX - print others as strings of hex? 6475115Sfenner */ 65146773Ssam if (EXTRACT_16BITS(&sllp->sll_halen) == 6) 6675115Sfenner (void)printf("%s ", etheraddr_string(sllp->sll_addr)); 6775115Sfenner 68147899Ssam if (!qflag) { 69147899Ssam ether_type = EXTRACT_16BITS(&sllp->sll_protocol); 70147899Ssam 71147899Ssam if (ether_type <= ETHERMTU) { 72147899Ssam /* 73147899Ssam * Not an Ethernet type; what type is it? 74147899Ssam */ 75147899Ssam switch (ether_type) { 76147899Ssam 77147899Ssam case LINUX_SLL_P_802_3: 78147899Ssam /* 79147899Ssam * Ethernet_802.3 IPX frame. 80147899Ssam */ 81147899Ssam (void)printf("802.3"); 82147899Ssam break; 83147899Ssam 84147899Ssam case LINUX_SLL_P_802_2: 85147899Ssam /* 86147899Ssam * 802.2. 87147899Ssam */ 88214478Srpaulo (void)printf("802.2"); 89147899Ssam break; 90147899Ssam 91147899Ssam default: 92147899Ssam /* 93147899Ssam * What is it? 94147899Ssam */ 95147899Ssam (void)printf("ethertype Unknown (0x%04x)", 96147899Ssam ether_type); 97147899Ssam break; 98147899Ssam } 99147899Ssam } else { 100147899Ssam (void)printf("ethertype %s (0x%04x)", 101147899Ssam tok2str(ethertype_values, "Unknown", ether_type), 102147899Ssam ether_type); 103147899Ssam } 104147899Ssam (void)printf(", length %u: ", length); 105147899Ssam } 10675115Sfenner} 10775115Sfenner 10875115Sfenner/* 109127668Sbms * This is the top level routine of the printer. 'p' points to the 110127668Sbms * Linux "cooked capture" header of the packet, 'h->ts' is the timestamp, 111146773Ssam * 'h->len' is the length of the packet off the wire, and 'h->caplen' 11275115Sfenner * is the number of bytes actually captured. 11375115Sfenner */ 114127668Sbmsu_int 115127668Sbmssll_if_print(const struct pcap_pkthdr *h, const u_char *p) 11675115Sfenner{ 11775115Sfenner u_int caplen = h->caplen; 11875115Sfenner u_int length = h->len; 11975115Sfenner register const struct sll_header *sllp; 12075115Sfenner u_short ether_type; 12175115Sfenner u_short extracted_ethertype; 12275115Sfenner 12375115Sfenner if (caplen < SLL_HDR_LEN) { 12475115Sfenner /* 12575115Sfenner * XXX - this "can't happen" because "pcap-linux.c" always 12675115Sfenner * adds this many bytes of header to every packet in a 12775115Sfenner * cooked socket capture. 12875115Sfenner */ 12975115Sfenner printf("[|sll]"); 130127668Sbms return (caplen); 13175115Sfenner } 13275115Sfenner 13375115Sfenner sllp = (const struct sll_header *)p; 13475115Sfenner 13575115Sfenner if (eflag) 13675115Sfenner sll_print(sllp, length); 13775115Sfenner 13875115Sfenner /* 139127668Sbms * Go past the cooked-mode header. 14075115Sfenner */ 14175115Sfenner length -= SLL_HDR_LEN; 14275115Sfenner caplen -= SLL_HDR_LEN; 14375115Sfenner p += SLL_HDR_LEN; 14475115Sfenner 145214478Srpaulo ether_type = EXTRACT_16BITS(&sllp->sll_protocol); 14675115Sfenner 147214478Srpaulorecurse: 14875115Sfenner /* 14975115Sfenner * Is it (gag) an 802.3 encapsulation, or some non-Ethernet 15075115Sfenner * packet type? 15175115Sfenner */ 15275115Sfenner if (ether_type <= ETHERMTU) { 15375115Sfenner /* 15475115Sfenner * Yes - what type is it? 15575115Sfenner */ 15675115Sfenner switch (ether_type) { 15775115Sfenner 15898524Sfenner case LINUX_SLL_P_802_3: 15998524Sfenner /* 16098524Sfenner * Ethernet_802.3 IPX frame. 16198524Sfenner */ 16298524Sfenner ipx_print(p, length); 16398524Sfenner break; 16498524Sfenner 16575115Sfenner case LINUX_SLL_P_802_2: 16675115Sfenner /* 16775115Sfenner * 802.2. 16875115Sfenner * Try to print the LLC-layer header & higher layers. 16975115Sfenner */ 170127668Sbms if (llc_print(p, length, caplen, NULL, NULL, 171127668Sbms &extracted_ethertype) == 0) 17275115Sfenner goto unknown; /* unknown LLC type */ 17375115Sfenner break; 17475115Sfenner 17575115Sfenner default: 176172683Smlaier extracted_ethertype = 0; 177172683Smlaier /*FALLTHROUGH*/ 178172683Smlaier 17975115Sfenner unknown: 18075115Sfenner /* ether_type not known, print raw packet */ 18175115Sfenner if (!eflag) 18275115Sfenner sll_print(sllp, length + SLL_HDR_LEN); 18375115Sfenner if (extracted_ethertype) { 18475115Sfenner printf("(LLC %s) ", 18575115Sfenner etherproto_string(htons(extracted_ethertype))); 18675115Sfenner } 187162017Ssam if (!suppress_default_print) 18875115Sfenner default_print(p, caplen); 18975115Sfenner break; 19075115Sfenner } 191214478Srpaulo } else if (ether_type == ETHERTYPE_8021Q) { 192214478Srpaulo /* 193214478Srpaulo * Print VLAN information, and then go back and process 194214478Srpaulo * the enclosed type field. 195214478Srpaulo */ 196214478Srpaulo if (caplen < 4 || length < 4) { 197214478Srpaulo printf("[|vlan]"); 198214478Srpaulo return (SLL_HDR_LEN); 199214478Srpaulo } 200214478Srpaulo if (eflag) { 201214478Srpaulo u_int16_t tag = EXTRACT_16BITS(p); 202214478Srpaulo 203214478Srpaulo printf("vlan %u, p %u%s, ", 204214478Srpaulo tag & 0xfff, 205214478Srpaulo tag >> 13, 206214478Srpaulo (tag & 0x1000) ? ", CFI" : ""); 207214478Srpaulo } 208214478Srpaulo 209214478Srpaulo ether_type = EXTRACT_16BITS(p + 2); 210214478Srpaulo if (ether_type <= ETHERMTU) 211214478Srpaulo ether_type = LINUX_SLL_P_802_2; 212214478Srpaulo if (!qflag) { 213214478Srpaulo (void)printf("ethertype %s, ", 214214478Srpaulo tok2str(ethertype_values, "Unknown", ether_type)); 215214478Srpaulo } 216214478Srpaulo p += 4; 217214478Srpaulo length -= 4; 218214478Srpaulo caplen -= 4; 219214478Srpaulo goto recurse; 220214478Srpaulo } else { 221235530Sdelphij if (ethertype_print(gndo, ether_type, p, length, caplen) == 0) { 222214478Srpaulo /* ether_type not known, print raw packet */ 223214478Srpaulo if (!eflag) 224214478Srpaulo sll_print(sllp, length + SLL_HDR_LEN); 225214478Srpaulo if (!suppress_default_print) 226214478Srpaulo default_print(p, caplen); 227214478Srpaulo } 22875115Sfenner } 229127668Sbms 230127668Sbms return (SLL_HDR_LEN); 23175115Sfenner} 232