print-sll.c revision 1.6.2.1 1 1.1 christos /*
2 1.1 christos * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997
3 1.1 christos * The Regents of the University of California. All rights reserved.
4 1.1 christos *
5 1.1 christos * Redistribution and use in source and binary forms, with or without
6 1.1 christos * modification, are permitted provided that: (1) source code distributions
7 1.1 christos * retain the above copyright notice and this paragraph in its entirety, (2)
8 1.1 christos * distributions including binary code include the above copyright notice and
9 1.1 christos * this paragraph in its entirety in the documentation or other materials
10 1.1 christos * provided with the distribution, and (3) all advertising materials mentioning
11 1.1 christos * features or use of this software display the following acknowledgement:
12 1.1 christos * ``This product includes software developed by the University of California,
13 1.1 christos * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
14 1.1 christos * the University nor the names of its contributors may be used to endorse
15 1.1 christos * or promote products derived from this software without specific prior
16 1.1 christos * written permission.
17 1.1 christos * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
18 1.1 christos * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
19 1.1 christos * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
20 1.1 christos */
21 1.5 christos
22 1.2 christos #include <sys/cdefs.h>
23 1.1 christos #ifndef lint
24 1.6.2.1 pgoyette __RCSID("$NetBSD: print-sll.c,v 1.6.2.1 2017/03/20 06:56:23 pgoyette Exp $");
25 1.1 christos #endif
26 1.1 christos
27 1.6.2.1 pgoyette /* \summary: Linux cooked sockets capture printer */
28 1.6.2.1 pgoyette
29 1.1 christos #ifdef HAVE_CONFIG_H
30 1.1 christos #include "config.h"
31 1.1 christos #endif
32 1.1 christos
33 1.6.2.1 pgoyette #include <netdissect-stdinc.h>
34 1.1 christos
35 1.6.2.1 pgoyette #include "netdissect.h"
36 1.1 christos #include "addrtoname.h"
37 1.1 christos #include "ethertype.h"
38 1.1 christos #include "extract.h"
39 1.1 christos
40 1.1 christos #include "ether.h"
41 1.5 christos
42 1.5 christos /*
43 1.5 christos * For captures on Linux cooked sockets, we construct a fake header
44 1.5 christos * that includes:
45 1.5 christos *
46 1.5 christos * a 2-byte "packet type" which is one of:
47 1.5 christos *
48 1.5 christos * LINUX_SLL_HOST packet was sent to us
49 1.5 christos * LINUX_SLL_BROADCAST packet was broadcast
50 1.5 christos * LINUX_SLL_MULTICAST packet was multicast
51 1.5 christos * LINUX_SLL_OTHERHOST packet was sent to somebody else
52 1.5 christos * LINUX_SLL_OUTGOING packet was sent *by* us;
53 1.5 christos *
54 1.5 christos * a 2-byte Ethernet protocol field;
55 1.5 christos *
56 1.5 christos * a 2-byte link-layer type;
57 1.5 christos *
58 1.5 christos * a 2-byte link-layer address length;
59 1.5 christos *
60 1.5 christos * an 8-byte source link-layer address, whose actual length is
61 1.5 christos * specified by the previous value.
62 1.5 christos *
63 1.5 christos * All fields except for the link-layer address are in network byte order.
64 1.5 christos *
65 1.5 christos * DO NOT change the layout of this structure, or change any of the
66 1.5 christos * LINUX_SLL_ values below. If you must change the link-layer header
67 1.5 christos * for a "cooked" Linux capture, introduce a new DLT_ type (ask
68 1.5 christos * "tcpdump-workers (at) lists.tcpdump.org" for one, so that you don't give it
69 1.5 christos * a value that collides with a value already being used), and use the
70 1.5 christos * new header in captures of that type, so that programs that can
71 1.5 christos * handle DLT_LINUX_SLL captures will continue to handle them correctly
72 1.5 christos * without any change, and so that capture files with different headers
73 1.5 christos * can be told apart and programs that read them can dissect the
74 1.5 christos * packets in them.
75 1.5 christos *
76 1.5 christos * This structure, and the #defines below, must be the same in the
77 1.5 christos * libpcap and tcpdump versions of "sll.h".
78 1.5 christos */
79 1.5 christos
80 1.5 christos /*
81 1.5 christos * A DLT_LINUX_SLL fake link-layer header.
82 1.5 christos */
83 1.5 christos #define SLL_HDR_LEN 16 /* total header length */
84 1.5 christos #define SLL_ADDRLEN 8 /* length of address field */
85 1.5 christos
86 1.5 christos struct sll_header {
87 1.5 christos uint16_t sll_pkttype; /* packet type */
88 1.5 christos uint16_t sll_hatype; /* link-layer address type */
89 1.5 christos uint16_t sll_halen; /* link-layer address length */
90 1.5 christos uint8_t sll_addr[SLL_ADDRLEN]; /* link-layer address */
91 1.5 christos uint16_t sll_protocol; /* protocol */
92 1.5 christos };
93 1.5 christos
94 1.5 christos /*
95 1.5 christos * The LINUX_SLL_ values for "sll_pkttype"; these correspond to the
96 1.5 christos * PACKET_ values on Linux, but are defined here so that they're
97 1.5 christos * available even on systems other than Linux, and so that they
98 1.5 christos * don't change even if the PACKET_ values change.
99 1.5 christos */
100 1.5 christos #define LINUX_SLL_HOST 0
101 1.5 christos #define LINUX_SLL_BROADCAST 1
102 1.5 christos #define LINUX_SLL_MULTICAST 2
103 1.5 christos #define LINUX_SLL_OTHERHOST 3
104 1.5 christos #define LINUX_SLL_OUTGOING 4
105 1.5 christos
106 1.5 christos /*
107 1.5 christos * The LINUX_SLL_ values for "sll_protocol"; these correspond to the
108 1.5 christos * ETH_P_ values on Linux, but are defined here so that they're
109 1.5 christos * available even on systems other than Linux. We assume, for now,
110 1.5 christos * that the ETH_P_ values won't change in Linux; if they do, then:
111 1.5 christos *
112 1.5 christos * if we don't translate them in "pcap-linux.c", capture files
113 1.5 christos * won't necessarily be readable if captured on a system that
114 1.5 christos * defines ETH_P_ values that don't match these values;
115 1.5 christos *
116 1.5 christos * if we do translate them in "pcap-linux.c", that makes life
117 1.5 christos * unpleasant for the BPF code generator, as the values you test
118 1.5 christos * for in the kernel aren't the values that you test for when
119 1.5 christos * reading a capture file, so the fixup code run on BPF programs
120 1.5 christos * handed to the kernel ends up having to do more work.
121 1.5 christos *
122 1.5 christos * Add other values here as necessary, for handling packet types that
123 1.5 christos * might show up on non-Ethernet, non-802.x networks. (Not all the ones
124 1.5 christos * in the Linux "if_ether.h" will, I suspect, actually show up in
125 1.5 christos * captures.)
126 1.5 christos */
127 1.5 christos #define LINUX_SLL_P_802_3 0x0001 /* Novell 802.3 frames without 802.2 LLC header */
128 1.5 christos #define LINUX_SLL_P_802_2 0x0004 /* 802.2 frames (not D/I/X Ethernet) */
129 1.1 christos
130 1.4 christos static const struct tok sll_pkttype_values[] = {
131 1.1 christos { LINUX_SLL_HOST, "In" },
132 1.1 christos { LINUX_SLL_BROADCAST, "B" },
133 1.1 christos { LINUX_SLL_MULTICAST, "M" },
134 1.1 christos { LINUX_SLL_OTHERHOST, "P" },
135 1.1 christos { LINUX_SLL_OUTGOING, "Out" },
136 1.1 christos { 0, NULL}
137 1.1 christos };
138 1.1 christos
139 1.1 christos static inline void
140 1.5 christos sll_print(netdissect_options *ndo, register const struct sll_header *sllp, u_int length)
141 1.1 christos {
142 1.1 christos u_short ether_type;
143 1.1 christos
144 1.5 christos ND_PRINT((ndo, "%3s ",tok2str(sll_pkttype_values,"?",EXTRACT_16BITS(&sllp->sll_pkttype))));
145 1.1 christos
146 1.1 christos /*
147 1.1 christos * XXX - check the link-layer address type value?
148 1.1 christos * For now, we just assume 6 means Ethernet.
149 1.1 christos * XXX - print others as strings of hex?
150 1.1 christos */
151 1.1 christos if (EXTRACT_16BITS(&sllp->sll_halen) == 6)
152 1.5 christos ND_PRINT((ndo, "%s ", etheraddr_string(ndo, sllp->sll_addr)));
153 1.1 christos
154 1.5 christos if (!ndo->ndo_qflag) {
155 1.1 christos ether_type = EXTRACT_16BITS(&sllp->sll_protocol);
156 1.5 christos
157 1.1 christos if (ether_type <= ETHERMTU) {
158 1.1 christos /*
159 1.1 christos * Not an Ethernet type; what type is it?
160 1.1 christos */
161 1.1 christos switch (ether_type) {
162 1.1 christos
163 1.1 christos case LINUX_SLL_P_802_3:
164 1.1 christos /*
165 1.1 christos * Ethernet_802.3 IPX frame.
166 1.1 christos */
167 1.5 christos ND_PRINT((ndo, "802.3"));
168 1.1 christos break;
169 1.1 christos
170 1.1 christos case LINUX_SLL_P_802_2:
171 1.1 christos /*
172 1.1 christos * 802.2.
173 1.1 christos */
174 1.5 christos ND_PRINT((ndo, "802.2"));
175 1.1 christos break;
176 1.1 christos
177 1.1 christos default:
178 1.1 christos /*
179 1.1 christos * What is it?
180 1.1 christos */
181 1.5 christos ND_PRINT((ndo, "ethertype Unknown (0x%04x)",
182 1.5 christos ether_type));
183 1.1 christos break;
184 1.1 christos }
185 1.1 christos } else {
186 1.5 christos ND_PRINT((ndo, "ethertype %s (0x%04x)",
187 1.1 christos tok2str(ethertype_values, "Unknown", ether_type),
188 1.5 christos ether_type));
189 1.1 christos }
190 1.5 christos ND_PRINT((ndo, ", length %u: ", length));
191 1.1 christos }
192 1.1 christos }
193 1.1 christos
194 1.1 christos /*
195 1.1 christos * This is the top level routine of the printer. 'p' points to the
196 1.1 christos * Linux "cooked capture" header of the packet, 'h->ts' is the timestamp,
197 1.1 christos * 'h->len' is the length of the packet off the wire, and 'h->caplen'
198 1.1 christos * is the number of bytes actually captured.
199 1.1 christos */
200 1.1 christos u_int
201 1.5 christos sll_if_print(netdissect_options *ndo, const struct pcap_pkthdr *h, const u_char *p)
202 1.1 christos {
203 1.1 christos u_int caplen = h->caplen;
204 1.1 christos u_int length = h->len;
205 1.1 christos register const struct sll_header *sllp;
206 1.1 christos u_short ether_type;
207 1.6.2.1 pgoyette int llc_hdrlen;
208 1.6.2.1 pgoyette u_int hdrlen;
209 1.1 christos
210 1.1 christos if (caplen < SLL_HDR_LEN) {
211 1.1 christos /*
212 1.1 christos * XXX - this "can't happen" because "pcap-linux.c" always
213 1.1 christos * adds this many bytes of header to every packet in a
214 1.1 christos * cooked socket capture.
215 1.1 christos */
216 1.5 christos ND_PRINT((ndo, "[|sll]"));
217 1.1 christos return (caplen);
218 1.1 christos }
219 1.1 christos
220 1.1 christos sllp = (const struct sll_header *)p;
221 1.1 christos
222 1.5 christos if (ndo->ndo_eflag)
223 1.5 christos sll_print(ndo, sllp, length);
224 1.1 christos
225 1.1 christos /*
226 1.1 christos * Go past the cooked-mode header.
227 1.1 christos */
228 1.1 christos length -= SLL_HDR_LEN;
229 1.1 christos caplen -= SLL_HDR_LEN;
230 1.1 christos p += SLL_HDR_LEN;
231 1.6.2.1 pgoyette hdrlen = SLL_HDR_LEN;
232 1.1 christos
233 1.1 christos ether_type = EXTRACT_16BITS(&sllp->sll_protocol);
234 1.1 christos
235 1.1 christos recurse:
236 1.1 christos /*
237 1.1 christos * Is it (gag) an 802.3 encapsulation, or some non-Ethernet
238 1.1 christos * packet type?
239 1.1 christos */
240 1.1 christos if (ether_type <= ETHERMTU) {
241 1.1 christos /*
242 1.1 christos * Yes - what type is it?
243 1.1 christos */
244 1.1 christos switch (ether_type) {
245 1.1 christos
246 1.1 christos case LINUX_SLL_P_802_3:
247 1.1 christos /*
248 1.1 christos * Ethernet_802.3 IPX frame.
249 1.1 christos */
250 1.5 christos ipx_print(ndo, p, length);
251 1.1 christos break;
252 1.1 christos
253 1.1 christos case LINUX_SLL_P_802_2:
254 1.1 christos /*
255 1.1 christos * 802.2.
256 1.1 christos * Try to print the LLC-layer header & higher layers.
257 1.1 christos */
258 1.6.2.1 pgoyette llc_hdrlen = llc_print(ndo, p, length, caplen, NULL, NULL);
259 1.6.2.1 pgoyette if (llc_hdrlen < 0)
260 1.1 christos goto unknown; /* unknown LLC type */
261 1.6.2.1 pgoyette hdrlen += llc_hdrlen;
262 1.1 christos break;
263 1.1 christos
264 1.1 christos default:
265 1.1 christos /*FALLTHROUGH*/
266 1.1 christos
267 1.1 christos unknown:
268 1.6.2.1 pgoyette /* packet type not known, print raw packet */
269 1.5 christos if (!ndo->ndo_suppress_default_print)
270 1.5 christos ND_DEFAULTPRINT(p, caplen);
271 1.1 christos break;
272 1.1 christos }
273 1.1 christos } else if (ether_type == ETHERTYPE_8021Q) {
274 1.1 christos /*
275 1.1 christos * Print VLAN information, and then go back and process
276 1.1 christos * the enclosed type field.
277 1.1 christos */
278 1.6.2.1 pgoyette if (caplen < 4) {
279 1.6.2.1 pgoyette ND_PRINT((ndo, "[|vlan]"));
280 1.6.2.1 pgoyette return (hdrlen + caplen);
281 1.6.2.1 pgoyette }
282 1.6.2.1 pgoyette if (length < 4) {
283 1.5 christos ND_PRINT((ndo, "[|vlan]"));
284 1.6.2.1 pgoyette return (hdrlen + length);
285 1.1 christos }
286 1.5 christos if (ndo->ndo_eflag) {
287 1.5 christos uint16_t tag = EXTRACT_16BITS(p);
288 1.1 christos
289 1.6 christos ND_PRINT((ndo, "%s, ", ieee8021q_tci_string(tag)));
290 1.1 christos }
291 1.1 christos
292 1.1 christos ether_type = EXTRACT_16BITS(p + 2);
293 1.1 christos if (ether_type <= ETHERMTU)
294 1.1 christos ether_type = LINUX_SLL_P_802_2;
295 1.5 christos if (!ndo->ndo_qflag) {
296 1.5 christos ND_PRINT((ndo, "ethertype %s, ",
297 1.5 christos tok2str(ethertype_values, "Unknown", ether_type)));
298 1.1 christos }
299 1.1 christos p += 4;
300 1.1 christos length -= 4;
301 1.1 christos caplen -= 4;
302 1.6.2.1 pgoyette hdrlen += 4;
303 1.1 christos goto recurse;
304 1.1 christos } else {
305 1.6.2.1 pgoyette if (ethertype_print(ndo, ether_type, p, length, caplen, NULL, NULL) == 0) {
306 1.1 christos /* ether_type not known, print raw packet */
307 1.5 christos if (!ndo->ndo_eflag)
308 1.5 christos sll_print(ndo, sllp, length + SLL_HDR_LEN);
309 1.5 christos if (!ndo->ndo_suppress_default_print)
310 1.5 christos ND_DEFAULTPRINT(p, caplen);
311 1.1 christos }
312 1.1 christos }
313 1.1 christos
314 1.6.2.1 pgoyette return (hdrlen);
315 1.1 christos }
316