print-sll.c revision 111726
1183873Sraj/* 2183873Sraj * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997 3183873Sraj * The Regents of the University of California. All rights reserved. 4183873Sraj * 5183873Sraj * Redistribution and use in source and binary forms, with or without 6183873Sraj * modification, are permitted provided that: (1) source code distributions 7183873Sraj * retain the above copyright notice and this paragraph in its entirety, (2) 8183873Sraj * distributions including binary code include the above copyright notice and 9183873Sraj * this paragraph in its entirety in the documentation or other materials 10191954Skuriyama * provided with the distribution, and (3) all advertising materials mentioning 11185478Ssam * features or use of this software display the following acknowledgement: 12183873Sraj * ``This product includes software developed by the University of California, 13266328Sian * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of 14183873Sraj * the University nor the names of its contributors may be used to endorse 15183873Sraj * or promote products derived from this software without specific prior 16266328Sian * written permission. 17266328Sian * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED 18266328Sian * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF 19266328Sian * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 20266328Sian */ 21266331Sian#ifndef lint 22266328Sianstatic const char rcsid[] = 23266328Sian "@(#) $Header: /tcpdump/master/tcpdump/print-sll.c,v 1.6.4.1 2002/06/01 23:51:16 guy Exp $ (LBL)"; 24266328Sian#endif 25266328Sian 26266328Sian#ifdef HAVE_CONFIG_H 27191954Skuriyama#include "config.h" 28191954Skuriyama#endif 29191954Skuriyama 30191954Skuriyama#include <sys/param.h> 31183873Sraj#include <sys/time.h> 32191954Skuriyama#include <sys/socket.h> 33183873Sraj 34266328Sian#include <netinet/in.h> 35266328Sian 36266328Sian#include <stdio.h> 37266328Sian#include <string.h> 38183873Sraj#include <pcap.h> 39191954Skuriyama 40183873Sraj#include "interface.h" 41183873Sraj#include "addrtoname.h" 42183873Sraj#include "ethertype.h" 43183873Sraj 44191954Skuriyama#include "ether.h" 45191954Skuriyama#include "sll.h" 46266328Sian 47271339Sianstatic inline void 48266328Siansll_print(register const struct sll_header *sllp, u_int length) 49266328Sian{ 50191954Skuriyama u_short halen; 51271428Sian 52271428Sian switch (ntohs(sllp->sll_pkttype)) { 53191954Skuriyama 54183873Sraj case LINUX_SLL_HOST: 55185090Sraj (void)printf("< "); 56185090Sraj break; 57183873Sraj 58183873Sraj case LINUX_SLL_BROADCAST: 59183873Sraj (void)printf("B "); 60183873Sraj break; 61183873Sraj 62183873Sraj case LINUX_SLL_MULTICAST: 63183873Sraj (void)printf("M "); 64183873Sraj break; 65183873Sraj 66183873Sraj case LINUX_SLL_OTHERHOST: 67183873Sraj (void)printf("P "); 68183873Sraj break; 69183873Sraj 70183873Sraj case LINUX_SLL_OUTGOING: 71183873Sraj (void)printf("> "); 72227730Sraj break; 73227730Sraj 74227730Sraj default: 75227730Sraj (void)printf("? "); 76183873Sraj break; 77266328Sian } 78183873Sraj 79183873Sraj /* 80183873Sraj * XXX - check the link-layer address type value? 81183873Sraj * For now, we just assume 6 means Ethernet. 82183873Sraj * XXX - print others as strings of hex? 83183873Sraj */ 84183873Sraj halen = ntohs(sllp->sll_halen); 85183873Sraj if (halen == 6) 86183873Sraj (void)printf("%s ", etheraddr_string(sllp->sll_addr)); 87183873Sraj 88194845Sraj if (!qflag) 89194845Sraj (void)printf("%s ", etherproto_string(sllp->sll_protocol)); 90220982Smav (void)printf("%d: ", length); 91209131Sraj} 92235609Sgber 93235609Sgber/* 94235609Sgber * This is the top level routine of the printer. 'p' is the points 95209131Sraj * to the ether header of the packet, 'h->tv' is the timestamp, 96209131Sraj * 'h->length' is the length of the packet off the wire, and 'h->caplen' 97235609Sgber * is the number of bytes actually captured. 98209131Sraj */ 99void 100sll_if_print(u_char *user, const struct pcap_pkthdr *h, const u_char *p) 101{ 102 u_int caplen = h->caplen; 103 u_int length = h->len; 104 register const struct sll_header *sllp; 105 u_short pkttype; 106 struct ether_header ehdr; 107 u_short ether_type; 108 u_short extracted_ethertype; 109 110 ++infodelay; 111 ts_print(&h->ts); 112 113 if (caplen < SLL_HDR_LEN) { 114 /* 115 * XXX - this "can't happen" because "pcap-linux.c" always 116 * adds this many bytes of header to every packet in a 117 * cooked socket capture. 118 */ 119 printf("[|sll]"); 120 goto out; 121 } 122 123 sllp = (const struct sll_header *)p; 124 125 /* 126 * Fake up an Ethernet header for the benefit of printers that 127 * insist on "packetp" pointing to an Ethernet header. 128 */ 129 pkttype = ntohs(sllp->sll_pkttype); 130 131 /* The source address is in the packet header */ 132 memcpy(ehdr.ether_shost, sllp->sll_addr, ETHER_ADDR_LEN); 133 134 if (pkttype != LINUX_SLL_OUTGOING) { 135 /* 136 * We received this packet. 137 * 138 * We don't know the destination address, so 139 * we fake it - all 0's except that the 140 * bottommost bit of the bottommost octet 141 * is set for a unicast packet, all 0's except 142 * that the bottommost bit of the uppermost 143 * octet is set for a multicast packet, all 144 * 1's for a broadcast packet. 145 */ 146 if (pkttype == LINUX_SLL_BROADCAST) 147 memset(ehdr.ether_dhost, 0xFF, ETHER_ADDR_LEN); 148 else { 149 memset(ehdr.ether_dhost, 0, ETHER_ADDR_LEN); 150 if (pkttype == LINUX_SLL_MULTICAST) 151 ehdr.ether_dhost[0] = 1; 152 else 153 ehdr.ether_dhost[ETHER_ADDR_LEN-1] = 1; 154 } 155 } else { 156 /* 157 * We sent this packet; we don't know whether it's 158 * broadcast, multicast, or unicast, so just make 159 * the destination address all 0's. 160 */ 161 memset(ehdr.ether_dhost, 0, ETHER_ADDR_LEN); 162 } 163 164 if (eflag) 165 sll_print(sllp, length); 166 167 /* 168 * Some printers want to get back at the ethernet addresses, 169 * and/or check that they're not walking off the end of the packet. 170 * Rather than pass them all the way down, we set these globals. 171 */ 172 snapend = p + caplen; 173 /* 174 * Actually, the only printers that use packetp are print-arp.c 175 * and print-bootp.c, and they assume that packetp points to an 176 * Ethernet header. The right thing to do is to fix them to know 177 * which link type is in use when they excavate. XXX 178 */ 179 packetp = (u_char *)&ehdr; 180 181 length -= SLL_HDR_LEN; 182 caplen -= SLL_HDR_LEN; 183 p += SLL_HDR_LEN; 184 185 ether_type = ntohs(sllp->sll_protocol); 186 187 /* 188 * Is it (gag) an 802.3 encapsulation, or some non-Ethernet 189 * packet type? 190 */ 191 extracted_ethertype = 0; 192 if (ether_type <= ETHERMTU) { 193 /* 194 * Yes - what type is it? 195 */ 196 switch (ether_type) { 197 198 case LINUX_SLL_P_802_3: 199 /* 200 * Ethernet_802.3 IPX frame. 201 */ 202 ipx_print(p, length); 203 break; 204 205 case LINUX_SLL_P_802_2: 206 /* 207 * 802.2. 208 * Try to print the LLC-layer header & higher layers. 209 */ 210 if (llc_print(p, length, caplen, ESRC(&ehdr), 211 EDST(&ehdr), &extracted_ethertype) == 0) 212 goto unknown; /* unknown LLC type */ 213 break; 214 215 default: 216 unknown: 217 /* ether_type not known, print raw packet */ 218 if (!eflag) 219 sll_print(sllp, length + SLL_HDR_LEN); 220 if (extracted_ethertype) { 221 printf("(LLC %s) ", 222 etherproto_string(htons(extracted_ethertype))); 223 } 224 if (!xflag && !qflag) 225 default_print(p, caplen); 226 break; 227 } 228 } else if (ether_encap_print(ether_type, p, length, caplen, 229 &extracted_ethertype) == 0) { 230 /* ether_type not known, print raw packet */ 231 if (!eflag) 232 sll_print(sllp, length + SLL_HDR_LEN); 233 if (!xflag && !qflag) 234 default_print(p, caplen); 235 } 236 if (xflag) 237 default_print(p, caplen); 238 out: 239 putchar('\n'); 240 --infodelay; 241 if (infoprint) 242 info(0); 243} 244