1/*
2 * Copyright (c) 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 * pcap-common.c - common code for pcap and pcapng files
22 */
23
24#ifdef HAVE_CONFIG_H
25#include <config.h>
26#endif
27
28#include <pcap-types.h>
29
30#include "pcap-int.h"
31#include "extract.h"
32#include "pcap-usb-linux-common.h"
33
34#include "pcap-util.h"
35
36#include "pflog.h"
37#include "pcap/can_socketcan.h"
38#include "pcap/sll.h"
39#include "pcap/usb.h"
40#include "pcap/nflog.h"
41
42/*
43 * Most versions of the DLT_PFLOG pseudo-header have UID and PID fields
44 * that are saved in host byte order.
45 *
46 * When reading a DLT_PFLOG packet, we need to convert those fields from
47 * the byte order of the host that wrote the file to this host's byte
48 * order.
49 */
50static void
51swap_pflog_header(const struct pcap_pkthdr *hdr, u_char *buf)
52{
53	u_int caplen = hdr->caplen;
54	u_int length = hdr->len;
55	u_int pfloghdr_length;
56	struct pfloghdr *pflhdr = (struct pfloghdr *)buf;
57
58	if (caplen < (u_int) (offsetof(struct pfloghdr, uid) + sizeof pflhdr->uid) ||
59	    length < (u_int) (offsetof(struct pfloghdr, uid) + sizeof pflhdr->uid)) {
60		/* Not enough data to have the uid field */
61		return;
62	}
63
64	pfloghdr_length = pflhdr->length;
65
66	if (pfloghdr_length < (u_int) (offsetof(struct pfloghdr, uid) + sizeof pflhdr->uid)) {
67		/* Header doesn't include uid field */
68		return;
69	}
70	pflhdr->uid = SWAPLONG(pflhdr->uid);
71
72	if (caplen < (u_int) (offsetof(struct pfloghdr, pid) + sizeof pflhdr->pid) ||
73	    length < (u_int) (offsetof(struct pfloghdr, pid) + sizeof pflhdr->pid)) {
74		/* Not enough data to have the pid field */
75		return;
76	}
77	if (pfloghdr_length < (u_int) (offsetof(struct pfloghdr, pid) + sizeof pflhdr->pid)) {
78		/* Header doesn't include pid field */
79		return;
80	}
81	pflhdr->pid = SWAPLONG(pflhdr->pid);
82
83	if (caplen < (u_int) (offsetof(struct pfloghdr, rule_uid) + sizeof pflhdr->rule_uid) ||
84	    length < (u_int) (offsetof(struct pfloghdr, rule_uid) + sizeof pflhdr->rule_uid)) {
85		/* Not enough data to have the rule_uid field */
86		return;
87	}
88	if (pfloghdr_length < (u_int) (offsetof(struct pfloghdr, rule_uid) + sizeof pflhdr->rule_uid)) {
89		/* Header doesn't include rule_uid field */
90		return;
91	}
92	pflhdr->rule_uid = SWAPLONG(pflhdr->rule_uid);
93
94	if (caplen < (u_int) (offsetof(struct pfloghdr, rule_pid) + sizeof pflhdr->rule_pid) ||
95	    length < (u_int) (offsetof(struct pfloghdr, rule_pid) + sizeof pflhdr->rule_pid)) {
96		/* Not enough data to have the rule_pid field */
97		return;
98	}
99	if (pfloghdr_length < (u_int) (offsetof(struct pfloghdr, rule_pid) + sizeof pflhdr->rule_pid)) {
100		/* Header doesn't include rule_pid field */
101		return;
102	}
103	pflhdr->rule_pid = SWAPLONG(pflhdr->rule_pid);
104}
105
106/*
107 * DLT_LINUX_SLL packets with a protocol type of LINUX_SLL_P_CAN or
108 * LINUX_SLL_P_CANFD have SocketCAN headers in front of the payload,
109 * with the CAN ID being in host byte order.
110 *
111 * When reading a DLT_LINUX_SLL packet, we need to check for those
112 * packets and convert the CAN ID from the byte order of the host that
113 * wrote the file to this host's byte order.
114 */
115static void
116swap_linux_sll_header(const struct pcap_pkthdr *hdr, u_char *buf)
117{
118	u_int caplen = hdr->caplen;
119	u_int length = hdr->len;
120	struct sll_header *shdr = (struct sll_header *)buf;
121	uint16_t protocol;
122	pcap_can_socketcan_hdr *chdr;
123
124	if (caplen < (u_int) sizeof(struct sll_header) ||
125	    length < (u_int) sizeof(struct sll_header)) {
126		/* Not enough data to have the protocol field */
127		return;
128	}
129
130	protocol = EXTRACT_BE_U_2(&shdr->sll_protocol);
131	if (protocol != LINUX_SLL_P_CAN && protocol != LINUX_SLL_P_CANFD)
132		return;
133
134	/*
135	 * SocketCAN packet; fix up the packet's header.
136	 */
137	chdr = (pcap_can_socketcan_hdr *)(buf + sizeof(struct sll_header));
138	if (caplen < (u_int) sizeof(struct sll_header) + sizeof(chdr->can_id) ||
139	    length < (u_int) sizeof(struct sll_header) + sizeof(chdr->can_id)) {
140		/* Not enough data to have the CAN ID */
141		return;
142	}
143	chdr->can_id = SWAPLONG(chdr->can_id);
144}
145
146/*
147 * The same applies for DLT_LINUX_SLL2.
148 */
149static void
150swap_linux_sll2_header(const struct pcap_pkthdr *hdr, u_char *buf)
151{
152	u_int caplen = hdr->caplen;
153	u_int length = hdr->len;
154	struct sll2_header *shdr = (struct sll2_header *)buf;
155	uint16_t protocol;
156	pcap_can_socketcan_hdr *chdr;
157
158	if (caplen < (u_int) sizeof(struct sll2_header) ||
159	    length < (u_int) sizeof(struct sll2_header)) {
160		/* Not enough data to have the protocol field */
161		return;
162	}
163
164	protocol = EXTRACT_BE_U_2(&shdr->sll2_protocol);
165	if (protocol != LINUX_SLL_P_CAN && protocol != LINUX_SLL_P_CANFD)
166		return;
167
168	/*
169	 * SocketCAN packet; fix up the packet's header.
170	 */
171	chdr = (pcap_can_socketcan_hdr *)(buf + sizeof(struct sll2_header));
172	if (caplen < (u_int) sizeof(struct sll2_header) + sizeof(chdr->can_id) ||
173	    length < (u_int) sizeof(struct sll2_header) + sizeof(chdr->can_id)) {
174		/* Not enough data to have the CAN ID */
175		return;
176	}
177	chdr->can_id = SWAPLONG(chdr->can_id);
178}
179
180/*
181 * The DLT_USB_LINUX and DLT_USB_LINUX_MMAPPED headers are in host
182 * byte order when capturing (it's supplied directly from a
183 * memory-mapped buffer shared by the kernel).
184 *
185 * When reading a DLT_USB_LINUX or DLT_USB_LINUX_MMAPPED packet, we
186 * need to convert it from the byte order of the host that wrote the
187 * file to this host's byte order.
188 */
189static void
190swap_linux_usb_header(const struct pcap_pkthdr *hdr, u_char *buf,
191    int header_len_64_bytes)
192{
193	pcap_usb_header_mmapped *uhdr = (pcap_usb_header_mmapped *)buf;
194	bpf_u_int32 offset = 0;
195
196	/*
197	 * "offset" is the offset *past* the field we're swapping;
198	 * we skip the field *before* checking to make sure
199	 * the captured data length includes the entire field.
200	 */
201
202	/*
203	 * The URB id is a totally opaque value; do we really need to
204	 * convert it to the reading host's byte order???
205	 */
206	offset += 8;			/* skip past id */
207	if (hdr->caplen < offset)
208		return;
209	uhdr->id = SWAPLL(uhdr->id);
210
211	offset += 4;			/* skip past various 1-byte fields */
212
213	offset += 2;			/* skip past bus_id */
214	if (hdr->caplen < offset)
215		return;
216	uhdr->bus_id = SWAPSHORT(uhdr->bus_id);
217
218	offset += 2;			/* skip past various 1-byte fields */
219
220	offset += 8;			/* skip past ts_sec */
221	if (hdr->caplen < offset)
222		return;
223	uhdr->ts_sec = SWAPLL(uhdr->ts_sec);
224
225	offset += 4;			/* skip past ts_usec */
226	if (hdr->caplen < offset)
227		return;
228	uhdr->ts_usec = SWAPLONG(uhdr->ts_usec);
229
230	offset += 4;			/* skip past status */
231	if (hdr->caplen < offset)
232		return;
233	uhdr->status = SWAPLONG(uhdr->status);
234
235	offset += 4;			/* skip past urb_len */
236	if (hdr->caplen < offset)
237		return;
238	uhdr->urb_len = SWAPLONG(uhdr->urb_len);
239
240	offset += 4;			/* skip past data_len */
241	if (hdr->caplen < offset)
242		return;
243	uhdr->data_len = SWAPLONG(uhdr->data_len);
244
245	if (uhdr->transfer_type == URB_ISOCHRONOUS) {
246		offset += 4;			/* skip past s.iso.error_count */
247		if (hdr->caplen < offset)
248			return;
249		uhdr->s.iso.error_count = SWAPLONG(uhdr->s.iso.error_count);
250
251		offset += 4;			/* skip past s.iso.numdesc */
252		if (hdr->caplen < offset)
253			return;
254		uhdr->s.iso.numdesc = SWAPLONG(uhdr->s.iso.numdesc);
255	} else
256		offset += 8;			/* skip USB setup header */
257
258	/*
259	 * With the old header, there are no isochronous descriptors
260	 * after the header.
261	 *
262	 * With the new header, the actual number of descriptors in
263	 * the header is not s.iso.numdesc, it's ndesc - only the
264	 * first N descriptors, for some value of N, are put into
265	 * the header, and ndesc is set to the actual number copied.
266	 * In addition, if s.iso.numdesc is negative, no descriptors
267	 * are captured, and ndesc is set to 0.
268	 */
269	if (header_len_64_bytes) {
270		/*
271		 * This is either the "version 1" header, with
272		 * 16 bytes of additional fields at the end, or
273		 * a "version 0" header from a memory-mapped
274		 * capture, with 16 bytes of zeroed-out padding
275		 * at the end.  Byte swap them as if this were
276		 * a "version 1" header.
277		 */
278		offset += 4;			/* skip past interval */
279		if (hdr->caplen < offset)
280			return;
281		uhdr->interval = SWAPLONG(uhdr->interval);
282
283		offset += 4;			/* skip past start_frame */
284		if (hdr->caplen < offset)
285			return;
286		uhdr->start_frame = SWAPLONG(uhdr->start_frame);
287
288		offset += 4;			/* skip past xfer_flags */
289		if (hdr->caplen < offset)
290			return;
291		uhdr->xfer_flags = SWAPLONG(uhdr->xfer_flags);
292
293		offset += 4;			/* skip past ndesc */
294		if (hdr->caplen < offset)
295			return;
296		uhdr->ndesc = SWAPLONG(uhdr->ndesc);
297
298		if (uhdr->transfer_type == URB_ISOCHRONOUS) {
299			/* swap the values in struct linux_usb_isodesc */
300			usb_isodesc *pisodesc;
301			uint32_t i;
302
303			pisodesc = (usb_isodesc *)(void *)(buf+offset);
304			for (i = 0; i < uhdr->ndesc; i++) {
305				offset += 4;		/* skip past status */
306				if (hdr->caplen < offset)
307					return;
308				pisodesc->status = SWAPLONG(pisodesc->status);
309
310				offset += 4;		/* skip past offset */
311				if (hdr->caplen < offset)
312					return;
313				pisodesc->offset = SWAPLONG(pisodesc->offset);
314
315				offset += 4;		/* skip past len */
316				if (hdr->caplen < offset)
317					return;
318				pisodesc->len = SWAPLONG(pisodesc->len);
319
320				offset += 4;		/* skip past padding */
321
322				pisodesc++;
323			}
324		}
325	}
326}
327
328/*
329 * The DLT_NFLOG "packets" have a mixture of big-endian and host-byte-order
330 * data.  They begin with a fixed-length header with big-endian fields,
331 * followed by a set of TLVs, where the type and length are in host
332 * byte order but the values are either big-endian or are a raw byte
333 * sequence that's the same regardless of the host's byte order.
334 *
335 * When reading a DLT_NFLOG packet, we need to convert the type and
336 * length values from the byte order of the host that wrote the file
337 * to the byte order of this host.
338 */
339static void
340swap_nflog_header(const struct pcap_pkthdr *hdr, u_char *buf)
341{
342	u_char *p = buf;
343	nflog_hdr_t *nfhdr = (nflog_hdr_t *)buf;
344	nflog_tlv_t *tlv;
345	u_int caplen = hdr->caplen;
346	u_int length = hdr->len;
347	uint16_t size;
348
349	if (caplen < (u_int) sizeof(nflog_hdr_t) ||
350	    length < (u_int) sizeof(nflog_hdr_t)) {
351		/* Not enough data to have any TLVs. */
352		return;
353	}
354
355	if (nfhdr->nflog_version != 0) {
356		/* Unknown NFLOG version */
357		return;
358	}
359
360	length -= sizeof(nflog_hdr_t);
361	caplen -= sizeof(nflog_hdr_t);
362	p += sizeof(nflog_hdr_t);
363
364	while (caplen >= sizeof(nflog_tlv_t)) {
365		tlv = (nflog_tlv_t *) p;
366
367		/* Swap the type and length. */
368		tlv->tlv_type = SWAPSHORT(tlv->tlv_type);
369		tlv->tlv_length = SWAPSHORT(tlv->tlv_length);
370
371		/* Get the length of the TLV. */
372		size = tlv->tlv_length;
373		if (size % 4 != 0)
374			size += 4 - size % 4;
375
376		/* Is the TLV's length less than the minimum? */
377		if (size < sizeof(nflog_tlv_t)) {
378			/* Yes. Give up now. */
379			return;
380		}
381
382		/* Do we have enough data for the full TLV? */
383		if (caplen < size || length < size) {
384			/* No. */
385			return;
386		}
387
388		/* Skip over the TLV. */
389		length -= size;
390		caplen -= size;
391		p += size;
392	}
393}
394
395static void
396swap_pseudo_headers(int linktype, struct pcap_pkthdr *hdr, u_char *data)
397{
398	/*
399	 * Convert pseudo-headers from the byte order of
400	 * the host on which the file was saved to our
401	 * byte order, as necessary.
402	 */
403	switch (linktype) {
404
405	case DLT_PFLOG:
406		swap_pflog_header(hdr, data);
407		break;
408
409	case DLT_LINUX_SLL:
410		swap_linux_sll_header(hdr, data);
411		break;
412
413	case DLT_LINUX_SLL2:
414		swap_linux_sll2_header(hdr, data);
415		break;
416
417	case DLT_USB_LINUX:
418		swap_linux_usb_header(hdr, data, 0);
419		break;
420
421	case DLT_USB_LINUX_MMAPPED:
422		swap_linux_usb_header(hdr, data, 1);
423		break;
424
425	case DLT_NFLOG:
426		swap_nflog_header(hdr, data);
427		break;
428	}
429}
430
431void
432pcap_post_process(int linktype, int swapped, struct pcap_pkthdr *hdr,
433    u_char *data)
434{
435	if (swapped)
436		swap_pseudo_headers(linktype, hdr, data);
437
438	fixup_pcap_pkthdr(linktype, hdr, data);
439}
440
441void
442fixup_pcap_pkthdr(int linktype, struct pcap_pkthdr *hdr, const u_char *data)
443{
444	const pcap_usb_header_mmapped *usb_hdr;
445
446	usb_hdr = (const pcap_usb_header_mmapped *) data;
447	if (linktype == DLT_USB_LINUX_MMAPPED &&
448	    hdr->caplen >= sizeof (pcap_usb_header_mmapped)) {
449		/*
450		 * In older versions of libpcap, in memory-mapped captures,
451		 * the "on-the-bus length" for completion events for
452		 * incoming isochronous transfers was miscalculated; it
453		 * needed to be calculated based on the* offsets and lengths
454		 * in the descriptors, not on the raw URB length, but it
455		 * wasn't.
456		 *
457		 * If this packet contains transferred data (yes, data_flag
458		 * is 0 if we *do* have data), and the total on-the-network
459		 * length is equal to the value calculated from the raw URB
460		 * length, then it might be one of those transfers.
461		 *
462		 * We only do this if we have the full USB pseudo-header.
463		 */
464		if (!usb_hdr->data_flag &&
465		    hdr->len == sizeof(pcap_usb_header_mmapped) +
466		      (usb_hdr->ndesc * sizeof (usb_isodesc)) + usb_hdr->urb_len) {
467			/*
468			 * It might need fixing; fix it if it's a completion
469			 * event for an incoming isochronous transfer.
470			 */
471			fix_linux_usb_mmapped_length(hdr, data);
472		}
473	}
474}
475