]> The Tcpdump Group git mirrors - tcpdump/blob - print-sll.c
c1e42c20e65e897d04adc236259cbffe297ad5ad
[tcpdump] / print-sll.c
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
22 #ifdef HAVE_CONFIG_H
23 #include "config.h"
24 #endif
25
26 #include <tcpdump-stdinc.h>
27
28 #include <stdio.h>
29 #include <string.h>
30
31 #include "interface.h"
32 #include "addrtoname.h"
33 #include "ethertype.h"
34 #include "extract.h"
35
36 #include "ether.h"
37
38 /*
39 * For captures on Linux cooked sockets, we construct a fake header
40 * that includes:
41 *
42 * a 2-byte "packet type" which is one of:
43 *
44 * LINUX_SLL_HOST packet was sent to us
45 * LINUX_SLL_BROADCAST packet was broadcast
46 * LINUX_SLL_MULTICAST packet was multicast
47 * LINUX_SLL_OTHERHOST packet was sent to somebody else
48 * LINUX_SLL_OUTGOING packet was sent *by* us;
49 *
50 * a 2-byte Ethernet protocol field;
51 *
52 * a 2-byte link-layer type;
53 *
54 * a 2-byte link-layer address length;
55 *
56 * an 8-byte source link-layer address, whose actual length is
57 * specified by the previous value.
58 *
59 * All fields except for the link-layer address are in network byte order.
60 *
61 * DO NOT change the layout of this structure, or change any of the
62 * LINUX_SLL_ values below. If you must change the link-layer header
63 * for a "cooked" Linux capture, introduce a new DLT_ type (ask
64 * "tcpdump-workers@lists.tcpdump.org" for one, so that you don't give it
65 * a value that collides with a value already being used), and use the
66 * new header in captures of that type, so that programs that can
67 * handle DLT_LINUX_SLL captures will continue to handle them correctly
68 * without any change, and so that capture files with different headers
69 * can be told apart and programs that read them can dissect the
70 * packets in them.
71 *
72 * This structure, and the #defines below, must be the same in the
73 * libpcap and tcpdump versions of "sll.h".
74 */
75
76 /*
77 * A DLT_LINUX_SLL fake link-layer header.
78 */
79 #define SLL_HDR_LEN 16 /* total header length */
80 #define SLL_ADDRLEN 8 /* length of address field */
81
82 struct sll_header {
83 u_int16_t sll_pkttype; /* packet type */
84 u_int16_t sll_hatype; /* link-layer address type */
85 u_int16_t sll_halen; /* link-layer address length */
86 u_int8_t sll_addr[SLL_ADDRLEN]; /* link-layer address */
87 u_int16_t sll_protocol; /* protocol */
88 };
89
90 /*
91 * The LINUX_SLL_ values for "sll_pkttype"; these correspond to the
92 * PACKET_ values on Linux, but are defined here so that they're
93 * available even on systems other than Linux, and so that they
94 * don't change even if the PACKET_ values change.
95 */
96 #define LINUX_SLL_HOST 0
97 #define LINUX_SLL_BROADCAST 1
98 #define LINUX_SLL_MULTICAST 2
99 #define LINUX_SLL_OTHERHOST 3
100 #define LINUX_SLL_OUTGOING 4
101
102 /*
103 * The LINUX_SLL_ values for "sll_protocol"; these correspond to the
104 * ETH_P_ values on Linux, but are defined here so that they're
105 * available even on systems other than Linux. We assume, for now,
106 * that the ETH_P_ values won't change in Linux; if they do, then:
107 *
108 * if we don't translate them in "pcap-linux.c", capture files
109 * won't necessarily be readable if captured on a system that
110 * defines ETH_P_ values that don't match these values;
111 *
112 * if we do translate them in "pcap-linux.c", that makes life
113 * unpleasant for the BPF code generator, as the values you test
114 * for in the kernel aren't the values that you test for when
115 * reading a capture file, so the fixup code run on BPF programs
116 * handed to the kernel ends up having to do more work.
117 *
118 * Add other values here as necessary, for handling packet types that
119 * might show up on non-Ethernet, non-802.x networks. (Not all the ones
120 * in the Linux "if_ether.h" will, I suspect, actually show up in
121 * captures.)
122 */
123 #define LINUX_SLL_P_802_3 0x0001 /* Novell 802.3 frames without 802.2 LLC header */
124 #define LINUX_SLL_P_802_2 0x0004 /* 802.2 frames (not D/I/X Ethernet) */
125
126 static const struct tok sll_pkttype_values[] = {
127 { LINUX_SLL_HOST, "In" },
128 { LINUX_SLL_BROADCAST, "B" },
129 { LINUX_SLL_MULTICAST, "M" },
130 { LINUX_SLL_OTHERHOST, "P" },
131 { LINUX_SLL_OUTGOING, "Out" },
132 { 0, NULL}
133 };
134
135 static inline void
136 sll_print(register const struct sll_header *sllp, u_int length)
137 {
138 u_short ether_type;
139
140 printf("%3s ",tok2str(sll_pkttype_values,"?",EXTRACT_16BITS(&sllp->sll_pkttype)));
141
142 /*
143 * XXX - check the link-layer address type value?
144 * For now, we just assume 6 means Ethernet.
145 * XXX - print others as strings of hex?
146 */
147 if (EXTRACT_16BITS(&sllp->sll_halen) == 6)
148 (void)printf("%s ", etheraddr_string(sllp->sll_addr));
149
150 if (!qflag) {
151 ether_type = EXTRACT_16BITS(&sllp->sll_protocol);
152
153 if (ether_type <= ETHERMTU) {
154 /*
155 * Not an Ethernet type; what type is it?
156 */
157 switch (ether_type) {
158
159 case LINUX_SLL_P_802_3:
160 /*
161 * Ethernet_802.3 IPX frame.
162 */
163 (void)printf("802.3");
164 break;
165
166 case LINUX_SLL_P_802_2:
167 /*
168 * 802.2.
169 */
170 (void)printf("802.2");
171 break;
172
173 default:
174 /*
175 * What is it?
176 */
177 (void)printf("ethertype Unknown (0x%04x)",
178 ether_type);
179 break;
180 }
181 } else {
182 (void)printf("ethertype %s (0x%04x)",
183 tok2str(ethertype_values, "Unknown", ether_type),
184 ether_type);
185 }
186 (void)printf(", length %u: ", length);
187 }
188 }
189
190 /*
191 * This is the top level routine of the printer. 'p' points to the
192 * Linux "cooked capture" header of the packet, 'h->ts' is the timestamp,
193 * 'h->len' is the length of the packet off the wire, and 'h->caplen'
194 * is the number of bytes actually captured.
195 */
196 u_int
197 sll_if_print(const struct pcap_pkthdr *h, const u_char *p)
198 {
199 u_int caplen = h->caplen;
200 u_int length = h->len;
201 register const struct sll_header *sllp;
202 u_short ether_type;
203 u_short extracted_ethertype;
204
205 if (caplen < SLL_HDR_LEN) {
206 /*
207 * XXX - this "can't happen" because "pcap-linux.c" always
208 * adds this many bytes of header to every packet in a
209 * cooked socket capture.
210 */
211 printf("[|sll]");
212 return (caplen);
213 }
214
215 sllp = (const struct sll_header *)p;
216
217 if (eflag)
218 sll_print(sllp, length);
219
220 /*
221 * Go past the cooked-mode header.
222 */
223 length -= SLL_HDR_LEN;
224 caplen -= SLL_HDR_LEN;
225 p += SLL_HDR_LEN;
226
227 ether_type = EXTRACT_16BITS(&sllp->sll_protocol);
228
229 recurse:
230 /*
231 * Is it (gag) an 802.3 encapsulation, or some non-Ethernet
232 * packet type?
233 */
234 if (ether_type <= ETHERMTU) {
235 /*
236 * Yes - what type is it?
237 */
238 switch (ether_type) {
239
240 case LINUX_SLL_P_802_3:
241 /*
242 * Ethernet_802.3 IPX frame.
243 */
244 ipx_print(p, length);
245 break;
246
247 case LINUX_SLL_P_802_2:
248 /*
249 * 802.2.
250 * Try to print the LLC-layer header & higher layers.
251 */
252 if (llc_print(p, length, caplen, NULL, NULL,
253 &extracted_ethertype) == 0)
254 goto unknown; /* unknown LLC type */
255 break;
256
257 default:
258 extracted_ethertype = 0;
259 /*FALLTHROUGH*/
260
261 unknown:
262 /* ether_type not known, print raw packet */
263 if (!eflag)
264 sll_print(sllp, length + SLL_HDR_LEN);
265 if (extracted_ethertype) {
266 printf("(LLC %s) ",
267 etherproto_string(htons(extracted_ethertype)));
268 }
269 if (!suppress_default_print)
270 default_print(p, caplen);
271 break;
272 }
273 } else if (ether_type == ETHERTYPE_8021Q) {
274 /*
275 * Print VLAN information, and then go back and process
276 * the enclosed type field.
277 */
278 if (caplen < 4 || length < 4) {
279 printf("[|vlan]");
280 return (SLL_HDR_LEN);
281 }
282 if (eflag) {
283 u_int16_t tag = EXTRACT_16BITS(p);
284
285 printf("vlan %u, p %u%s, ",
286 tag & 0xfff,
287 tag >> 13,
288 (tag & 0x1000) ? ", CFI" : "");
289 }
290
291 ether_type = EXTRACT_16BITS(p + 2);
292 if (ether_type <= ETHERMTU)
293 ether_type = LINUX_SLL_P_802_2;
294 if (!qflag) {
295 (void)printf("ethertype %s, ",
296 tok2str(ethertype_values, "Unknown", ether_type));
297 }
298 p += 4;
299 length -= 4;
300 caplen -= 4;
301 goto recurse;
302 } else {
303 if (ethertype_print(gndo, ether_type, p, length, caplen) == 0) {
304 /* ether_type not known, print raw packet */
305 if (!eflag)
306 sll_print(sllp, length + SLL_HDR_LEN);
307 if (!suppress_default_print)
308 default_print(p, caplen);
309 }
310 }
311
312 return (SLL_HDR_LEN);
313 }