Coverage Report

Created: 2023-01-17 06:15

/src/libpcap/pcap-util.c
Line
Count
Source (jump to first uncovered line)
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
 */
50
static void
51
swap_pflog_header(const struct pcap_pkthdr *hdr, u_char *buf)
52
17.9k
{
53
17.9k
  u_int caplen = hdr->caplen;
54
17.9k
  u_int length = hdr->len;
55
17.9k
  u_int pfloghdr_length;
56
17.9k
  struct pfloghdr *pflhdr = (struct pfloghdr *)buf;
57
58
17.9k
  if (caplen < (u_int) (offsetof(struct pfloghdr, uid) + sizeof pflhdr->uid) ||
59
17.9k
      length < (u_int) (offsetof(struct pfloghdr, uid) + sizeof pflhdr->uid)) {
60
    /* Not enough data to have the uid field */
61
15.4k
    return;
62
15.4k
  }
63
64
2.58k
  pfloghdr_length = pflhdr->length;
65
66
2.58k
  if (pfloghdr_length < (u_int) (offsetof(struct pfloghdr, uid) + sizeof pflhdr->uid)) {
67
    /* Header doesn't include uid field */
68
774
    return;
69
774
  }
70
1.81k
  pflhdr->uid = SWAPLONG(pflhdr->uid);
71
72
1.81k
  if (caplen < (u_int) (offsetof(struct pfloghdr, pid) + sizeof pflhdr->pid) ||
73
1.81k
      length < (u_int) (offsetof(struct pfloghdr, pid) + sizeof pflhdr->pid)) {
74
    /* Not enough data to have the pid field */
75
268
    return;
76
268
  }
77
1.54k
  if (pfloghdr_length < (u_int) (offsetof(struct pfloghdr, pid) + sizeof pflhdr->pid)) {
78
    /* Header doesn't include pid field */
79
230
    return;
80
230
  }
81
1.31k
  pflhdr->pid = SWAPLONG(pflhdr->pid);
82
83
1.31k
  if (caplen < (u_int) (offsetof(struct pfloghdr, rule_uid) + sizeof pflhdr->rule_uid) ||
84
1.31k
      length < (u_int) (offsetof(struct pfloghdr, rule_uid) + sizeof pflhdr->rule_uid)) {
85
    /* Not enough data to have the rule_uid field */
86
254
    return;
87
254
  }
88
1.05k
  if (pfloghdr_length < (u_int) (offsetof(struct pfloghdr, rule_uid) + sizeof pflhdr->rule_uid)) {
89
    /* Header doesn't include rule_uid field */
90
560
    return;
91
560
  }
92
498
  pflhdr->rule_uid = SWAPLONG(pflhdr->rule_uid);
93
94
498
  if (caplen < (u_int) (offsetof(struct pfloghdr, rule_pid) + sizeof pflhdr->rule_pid) ||
95
498
      length < (u_int) (offsetof(struct pfloghdr, rule_pid) + sizeof pflhdr->rule_pid)) {
96
    /* Not enough data to have the rule_pid field */
97
106
    return;
98
106
  }
99
392
  if (pfloghdr_length < (u_int) (offsetof(struct pfloghdr, rule_pid) + sizeof pflhdr->rule_pid)) {
100
    /* Header doesn't include rule_pid field */
101
95
    return;
102
95
  }
103
297
  pflhdr->rule_pid = SWAPLONG(pflhdr->rule_pid);
104
297
}
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
 */
115
static void
116
swap_linux_sll_header(const struct pcap_pkthdr *hdr, u_char *buf)
117
11.8k
{
118
11.8k
  u_int caplen = hdr->caplen;
119
11.8k
  u_int length = hdr->len;
120
11.8k
  struct sll_header *shdr = (struct sll_header *)buf;
121
11.8k
  uint16_t protocol;
122
11.8k
  pcap_can_socketcan_hdr *chdr;
123
124
11.8k
  if (caplen < (u_int) sizeof(struct sll_header) ||
125
11.8k
      length < (u_int) sizeof(struct sll_header)) {
126
    /* Not enough data to have the protocol field */
127
6.15k
    return;
128
6.15k
  }
129
130
5.72k
  protocol = EXTRACT_BE_U_2(&shdr->sll_protocol);
131
5.72k
  if (protocol != LINUX_SLL_P_CAN && protocol != LINUX_SLL_P_CANFD)
132
4.55k
    return;
133
134
  /*
135
   * SocketCAN packet; fix up the packet's header.
136
   */
137
1.17k
  chdr = (pcap_can_socketcan_hdr *)(buf + sizeof(struct sll_header));
138
1.17k
  if (caplen < (u_int) sizeof(struct sll_header) + sizeof(chdr->can_id) ||
139
1.17k
      length < (u_int) sizeof(struct sll_header) + sizeof(chdr->can_id)) {
140
    /* Not enough data to have the CAN ID */
141
781
    return;
142
781
  }
143
392
  chdr->can_id = SWAPLONG(chdr->can_id);
144
392
}
145
146
/*
147
 * The same applies for DLT_LINUX_SLL2.
148
 */
149
static void
150
swap_linux_sll2_header(const struct pcap_pkthdr *hdr, u_char *buf)
151
0
{
152
0
  u_int caplen = hdr->caplen;
153
0
  u_int length = hdr->len;
154
0
  struct sll2_header *shdr = (struct sll2_header *)buf;
155
0
  uint16_t protocol;
156
0
  pcap_can_socketcan_hdr *chdr;
157
158
0
  if (caplen < (u_int) sizeof(struct sll2_header) ||
159
0
      length < (u_int) sizeof(struct sll2_header)) {
160
    /* Not enough data to have the protocol field */
161
0
    return;
162
0
  }
163
164
0
  protocol = EXTRACT_BE_U_2(&shdr->sll2_protocol);
165
0
  if (protocol != LINUX_SLL_P_CAN && protocol != LINUX_SLL_P_CANFD)
166
0
    return;
167
168
  /*
169
   * SocketCAN packet; fix up the packet's header.
170
   */
171
0
  chdr = (pcap_can_socketcan_hdr *)(buf + sizeof(struct sll2_header));
172
0
  if (caplen < (u_int) sizeof(struct sll2_header) + sizeof(chdr->can_id) ||
173
0
      length < (u_int) sizeof(struct sll2_header) + sizeof(chdr->can_id)) {
174
    /* Not enough data to have the CAN ID */
175
0
    return;
176
0
  }
177
0
  chdr->can_id = SWAPLONG(chdr->can_id);
178
0
}
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
 */
189
static void
190
swap_linux_usb_header(const struct pcap_pkthdr *hdr, u_char *buf,
191
    int header_len_64_bytes)
192
25.0k
{
193
25.0k
  pcap_usb_header_mmapped *uhdr = (pcap_usb_header_mmapped *)buf;
194
25.0k
  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
25.0k
  offset += 8;      /* skip past id */
207
25.0k
  if (hdr->caplen < offset)
208
12.1k
    return;
209
12.8k
  uhdr->id = SWAPLL(uhdr->id);
210
211
12.8k
  offset += 4;      /* skip past various 1-byte fields */
212
213
12.8k
  offset += 2;      /* skip past bus_id */
214
12.8k
  if (hdr->caplen < offset)
215
409
    return;
216
12.4k
  uhdr->bus_id = SWAPSHORT(uhdr->bus_id);
217
218
12.4k
  offset += 2;      /* skip past various 1-byte fields */
219
220
12.4k
  offset += 8;      /* skip past ts_sec */
221
12.4k
  if (hdr->caplen < offset)
222
401
    return;
223
12.0k
  uhdr->ts_sec = SWAPLL(uhdr->ts_sec);
224
225
12.0k
  offset += 4;      /* skip past ts_usec */
226
12.0k
  if (hdr->caplen < offset)
227
398
    return;
228
11.6k
  uhdr->ts_usec = SWAPLONG(uhdr->ts_usec);
229
230
11.6k
  offset += 4;      /* skip past status */
231
11.6k
  if (hdr->caplen < offset)
232
392
    return;
233
11.2k
  uhdr->status = SWAPLONG(uhdr->status);
234
235
11.2k
  offset += 4;      /* skip past urb_len */
236
11.2k
  if (hdr->caplen < offset)
237
2.22k
    return;
238
9.06k
  uhdr->urb_len = SWAPLONG(uhdr->urb_len);
239
240
9.06k
  offset += 4;      /* skip past data_len */
241
9.06k
  if (hdr->caplen < offset)
242
399
    return;
243
8.67k
  uhdr->data_len = SWAPLONG(uhdr->data_len);
244
245
8.67k
  if (uhdr->transfer_type == URB_ISOCHRONOUS) {
246
6.59k
    offset += 4;      /* skip past s.iso.error_count */
247
6.59k
    if (hdr->caplen < offset)
248
455
      return;
249
6.13k
    uhdr->s.iso.error_count = SWAPLONG(uhdr->s.iso.error_count);
250
251
6.13k
    offset += 4;      /* skip past s.iso.numdesc */
252
6.13k
    if (hdr->caplen < offset)
253
2.02k
      return;
254
4.10k
    uhdr->s.iso.numdesc = SWAPLONG(uhdr->s.iso.numdesc);
255
4.10k
  } else
256
2.07k
    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
6.18k
  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
5.74k
    offset += 4;      /* skip past interval */
279
5.74k
    if (hdr->caplen < offset)
280
439
      return;
281
5.30k
    uhdr->interval = SWAPLONG(uhdr->interval);
282
283
5.30k
    offset += 4;      /* skip past start_frame */
284
5.30k
    if (hdr->caplen < offset)
285
206
      return;
286
5.09k
    uhdr->start_frame = SWAPLONG(uhdr->start_frame);
287
288
5.09k
    offset += 4;      /* skip past xfer_flags */
289
5.09k
    if (hdr->caplen < offset)
290
329
      return;
291
4.76k
    uhdr->xfer_flags = SWAPLONG(uhdr->xfer_flags);
292
293
4.76k
    offset += 4;      /* skip past ndesc */
294
4.76k
    if (hdr->caplen < offset)
295
218
      return;
296
4.55k
    uhdr->ndesc = SWAPLONG(uhdr->ndesc);
297
298
4.55k
    if (uhdr->transfer_type == URB_ISOCHRONOUS) {
299
      /* swap the values in struct linux_usb_isodesc */
300
3.27k
      usb_isodesc *pisodesc;
301
3.27k
      uint32_t i;
302
303
3.27k
      pisodesc = (usb_isodesc *)(void *)(buf+offset);
304
104k
      for (i = 0; i < uhdr->ndesc; i++) {
305
102k
        offset += 4;    /* skip past status */
306
102k
        if (hdr->caplen < offset)
307
599
          return;
308
101k
        pisodesc->status = SWAPLONG(pisodesc->status);
309
310
101k
        offset += 4;    /* skip past offset */
311
101k
        if (hdr->caplen < offset)
312
113
          return;
313
101k
        pisodesc->offset = SWAPLONG(pisodesc->offset);
314
315
101k
        offset += 4;    /* skip past len */
316
101k
        if (hdr->caplen < offset)
317
239
          return;
318
101k
        pisodesc->len = SWAPLONG(pisodesc->len);
319
320
101k
        offset += 4;    /* skip past padding */
321
322
101k
        pisodesc++;
323
101k
      }
324
3.27k
    }
325
4.55k
  }
326
6.18k
}
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
 */
339
static void
340
swap_nflog_header(const struct pcap_pkthdr *hdr, u_char *buf)
341
2.24k
{
342
2.24k
  u_char *p = buf;
343
2.24k
  nflog_hdr_t *nfhdr = (nflog_hdr_t *)buf;
344
2.24k
  nflog_tlv_t *tlv;
345
2.24k
  u_int caplen = hdr->caplen;
346
2.24k
  u_int length = hdr->len;
347
2.24k
  uint16_t size;
348
349
2.24k
  if (caplen < (u_int) sizeof(nflog_hdr_t) ||
350
2.24k
      length < (u_int) sizeof(nflog_hdr_t)) {
351
    /* Not enough data to have any TLVs. */
352
722
    return;
353
722
  }
354
355
1.52k
  if (nfhdr->nflog_version != 0) {
356
    /* Unknown NFLOG version */
357
261
    return;
358
261
  }
359
360
1.26k
  length -= sizeof(nflog_hdr_t);
361
1.26k
  caplen -= sizeof(nflog_hdr_t);
362
1.26k
  p += sizeof(nflog_hdr_t);
363
364
2.31k
  while (caplen >= sizeof(nflog_tlv_t)) {
365
1.69k
    tlv = (nflog_tlv_t *) p;
366
367
    /* Swap the type and length. */
368
1.69k
    tlv->tlv_type = SWAPSHORT(tlv->tlv_type);
369
1.69k
    tlv->tlv_length = SWAPSHORT(tlv->tlv_length);
370
371
    /* Get the length of the TLV. */
372
1.69k
    size = tlv->tlv_length;
373
1.69k
    if (size % 4 != 0)
374
1.19k
      size += 4 - size % 4;
375
376
    /* Is the TLV's length less than the minimum? */
377
1.69k
    if (size < sizeof(nflog_tlv_t)) {
378
      /* Yes. Give up now. */
379
331
      return;
380
331
    }
381
382
    /* Do we have enough data for the full TLV? */
383
1.36k
    if (caplen < size || length < size) {
384
      /* No. */
385
311
      return;
386
311
    }
387
388
    /* Skip over the TLV. */
389
1.04k
    length -= size;
390
1.04k
    caplen -= size;
391
1.04k
    p += size;
392
1.04k
  }
393
1.26k
}
394
395
static void
396
swap_pseudo_headers(int linktype, struct pcap_pkthdr *hdr, u_char *data)
397
66.8k
{
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
66.8k
  switch (linktype) {
404
405
17.9k
  case DLT_PFLOG:
406
17.9k
    swap_pflog_header(hdr, data);
407
17.9k
    break;
408
409
11.8k
  case DLT_LINUX_SLL:
410
11.8k
    swap_linux_sll_header(hdr, data);
411
11.8k
    break;
412
413
0
  case DLT_LINUX_SLL2:
414
0
    swap_linux_sll2_header(hdr, data);
415
0
    break;
416
417
3.77k
  case DLT_USB_LINUX:
418
3.77k
    swap_linux_usb_header(hdr, data, 0);
419
3.77k
    break;
420
421
21.2k
  case DLT_USB_LINUX_MMAPPED:
422
21.2k
    swap_linux_usb_header(hdr, data, 1);
423
21.2k
    break;
424
425
2.24k
  case DLT_NFLOG:
426
2.24k
    swap_nflog_header(hdr, data);
427
2.24k
    break;
428
66.8k
  }
429
66.8k
}
430
431
void
432
pcap_post_process(int linktype, int swapped, struct pcap_pkthdr *hdr,
433
    u_char *data)
434
997k
{
435
997k
  if (swapped)
436
66.8k
    swap_pseudo_headers(linktype, hdr, data);
437
438
997k
  fixup_pcap_pkthdr(linktype, hdr, data);
439
997k
}
440
441
void
442
fixup_pcap_pkthdr(int linktype, struct pcap_pkthdr *hdr, const u_char *data)
443
997k
{
444
997k
  const pcap_usb_header_mmapped *usb_hdr;
445
446
997k
  usb_hdr = (const pcap_usb_header_mmapped *) data;
447
997k
  if (linktype == DLT_USB_LINUX_MMAPPED &&
448
997k
      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
4.84k
    if (!usb_hdr->data_flag &&
465
4.84k
        hdr->len == sizeof(pcap_usb_header_mmapped) +
466
4.42k
          (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
2.64k
      fix_linux_usb_mmapped_length(hdr, data);
472
2.64k
    }
473
4.84k
  }
474
997k
}