1 /* 2 * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997 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[] = 23 "@(#) $Header: /tcpdump/master/tcpdump/print-sll.c,v 1.6 2001/07/05 18:54:18 guy Exp $ (LBL)"; 24 #endif 25 26 #ifdef HAVE_CONFIG_H 27 #include "config.h" 28 #endif 29 30 #include <sys/param.h> 31 #include <sys/time.h> 32 #include <sys/socket.h> 33 34 struct mbuf; 35 struct rtentry; 36 37 #include <netinet/in.h> 38 39 #include <stdio.h> 40 #include <string.h> 41 #include <pcap.h> 42 43 #include "interface.h" 44 #include "addrtoname.h" 45 #include "ethertype.h" 46 47 #include "ether.h" 48 #include "sll.h" 49 50 static inline void 51 sll_print(register const struct sll_header *sllp, u_int length) 52 { 53 u_short halen; 54 55 switch (ntohs(sllp->sll_pkttype)) { 56 57 case LINUX_SLL_HOST: 58 (void)printf("< "); 59 break; 60 61 case LINUX_SLL_BROADCAST: 62 (void)printf("B "); 63 break; 64 65 case LINUX_SLL_MULTICAST: 66 (void)printf("M "); 67 break; 68 69 case LINUX_SLL_OTHERHOST: 70 (void)printf("P "); 71 break; 72 73 case LINUX_SLL_OUTGOING: 74 (void)printf("> "); 75 break; 76 77 default: 78 (void)printf("? "); 79 break; 80 } 81 82 /* 83 * XXX - check the link-layer address type value? 84 * For now, we just assume 6 means Ethernet. 85 * XXX - print others as strings of hex? 86 */ 87 halen = ntohs(sllp->sll_halen); 88 if (halen == 6) 89 (void)printf("%s ", etheraddr_string(sllp->sll_addr)); 90 91 if (!qflag) 92 (void)printf("%s ", etherproto_string(sllp->sll_protocol)); 93 (void)printf("%d: ", length); 94 } 95 96 /* 97 * This is the top level routine of the printer. 'p' is the points 98 * to the ether header of the packet, 'h->tv' is the timestamp, 99 * 'h->length' is the length of the packet off the wire, and 'h->caplen' 100 * is the number of bytes actually captured. 101 */ 102 void 103 sll_if_print(u_char *user, const struct pcap_pkthdr *h, const u_char *p) 104 { 105 u_int caplen = h->caplen; 106 u_int length = h->len; 107 register const struct sll_header *sllp; 108 u_short pkttype; 109 struct ether_header ehdr; 110 u_short ether_type; 111 u_short extracted_ethertype; 112 113 ++infodelay; 114 ts_print(&h->ts); 115 116 if (caplen < SLL_HDR_LEN) { 117 /* 118 * XXX - this "can't happen" because "pcap-linux.c" always 119 * adds this many bytes of header to every packet in a 120 * cooked socket capture. 121 */ 122 printf("[|sll]"); 123 goto out; 124 } 125 126 sllp = (const struct sll_header *)p; 127 128 /* 129 * Fake up an Ethernet header for the benefit of printers that 130 * insist on "packetp" pointing to an Ethernet header. 131 */ 132 pkttype = ntohs(sllp->sll_pkttype); 133 134 /* The source address is in the packet header */ 135 memcpy(ehdr.ether_shost, sllp->sll_addr, ETHER_ADDR_LEN); 136 137 if (pkttype != LINUX_SLL_OUTGOING) { 138 /* 139 * We received this packet. 140 * 141 * We don't know the destination address, so 142 * we fake it - all 0's except that the 143 * bottommost bit of the bottommost octet 144 * is set for a unicast packet, all 0's except 145 * that the bottommost bit of the uppermost 146 * octet is set for a multicast packet, all 147 * 1's for a broadcast packet. 148 */ 149 if (pkttype == LINUX_SLL_BROADCAST) 150 memset(ehdr.ether_dhost, 0xFF, ETHER_ADDR_LEN); 151 else { 152 memset(ehdr.ether_dhost, 0, ETHER_ADDR_LEN); 153 if (pkttype == LINUX_SLL_MULTICAST) 154 ehdr.ether_dhost[0] = 1; 155 else 156 ehdr.ether_dhost[ETHER_ADDR_LEN-1] = 1; 157 } 158 } else { 159 /* 160 * We sent this packet; we don't know whether it's 161 * broadcast, multicast, or unicast, so just make 162 * the destination address all 0's. 163 */ 164 memset(ehdr.ether_dhost, 0, ETHER_ADDR_LEN); 165 } 166 167 if (eflag) 168 sll_print(sllp, length); 169 170 /* 171 * Some printers want to get back at the ethernet addresses, 172 * and/or check that they're not walking off the end of the packet. 173 * Rather than pass them all the way down, we set these globals. 174 */ 175 snapend = p + caplen; 176 /* 177 * Actually, the only printers that use packetp are print-arp.c 178 * and print-bootp.c, and they assume that packetp points to an 179 * Ethernet header. The right thing to do is to fix them to know 180 * which link type is in use when they excavate. XXX 181 */ 182 packetp = (u_char *)&ehdr; 183 184 length -= SLL_HDR_LEN; 185 caplen -= SLL_HDR_LEN; 186 p += SLL_HDR_LEN; 187 188 ether_type = ntohs(sllp->sll_protocol); 189 190 /* 191 * Is it (gag) an 802.3 encapsulation, or some non-Ethernet 192 * packet type? 193 */ 194 extracted_ethertype = 0; 195 if (ether_type <= ETHERMTU) { 196 /* 197 * Yes - what type is it? 198 */ 199 switch (ether_type) { 200 201 case LINUX_SLL_P_802_3: 202 /* 203 * Ethernet_802.3 IPX frame. 204 */ 205 ipx_print(p, length); 206 break; 207 208 case LINUX_SLL_P_802_2: 209 /* 210 * 802.2. 211 * Try to print the LLC-layer header & higher layers. 212 */ 213 if (llc_print(p, length, caplen, ESRC(&ehdr), 214 EDST(&ehdr), &extracted_ethertype) == 0) 215 goto unknown; /* unknown LLC type */ 216 break; 217 218 default: 219 unknown: 220 /* ether_type not known, print raw packet */ 221 if (!eflag) 222 sll_print(sllp, length + SLL_HDR_LEN); 223 if (extracted_ethertype) { 224 printf("(LLC %s) ", 225 etherproto_string(htons(extracted_ethertype))); 226 } 227 if (!xflag && !qflag) 228 default_print(p, caplen); 229 break; 230 } 231 } else if (ether_encap_print(ether_type, p, length, caplen, 232 &extracted_ethertype) == 0) { 233 /* ether_type not known, print raw packet */ 234 if (!eflag) 235 sll_print(sllp, length + SLL_HDR_LEN); 236 if (!xflag && !qflag) 237 default_print(p, caplen); 238 } 239 if (xflag) 240 default_print(p, caplen); 241 out: 242 putchar('\n'); 243 --infodelay; 244 if (infoprint) 245 info(0); 246 } 247