forked from osmocom/wireshark
pcap: process the subfields of the link-layer-type-plus-stuff field.
Extract the FCS length information from that field, and reject captures that have a non-zero "class" field (the 10-bit reserved field that was once intended to allow other "classes" of link layer type, with class 0 being "LINKTYPE_ values", but the original use case doesn't appear ever to have been used).
This commit is contained in:
parent
5db8d0930a
commit
e999b0a4d2
|
@ -55,6 +55,7 @@ typedef struct {
|
|||
guint16 version_major;
|
||||
guint16 version_minor;
|
||||
pcap_variant_t variant;
|
||||
int fcs_len;
|
||||
void *encap_priv;
|
||||
} libpcap_t;
|
||||
|
||||
|
@ -87,6 +88,62 @@ static gboolean libpcap_dump_pcap_ss991029(wtap_dumper *wdh,
|
|||
static gboolean libpcap_dump_pcap_nokia(wtap_dumper *wdh, const wtap_rec *rec,
|
||||
const guint8 *pd, int *err, gchar **err_info);
|
||||
|
||||
/*
|
||||
* Subfields of the field containing the link-layer header type.
|
||||
*
|
||||
* Link-layer header types are assigned for both pcap and
|
||||
* pcapng, and the same value must work with both. In pcapng,
|
||||
* the link-layer header type field in an Interface Description
|
||||
* Block is 16 bits, so only the bottommost 16 bits of the
|
||||
* link-layer header type in a pcap file can be used for the
|
||||
* header type value.
|
||||
*
|
||||
* In libpcap, the upper 16 bits, from the top down, are divided into:
|
||||
*
|
||||
* A 4-bit "FCS length" field, to allow the FCS length to
|
||||
* be specified, just as it can be specified in the if_fcslen
|
||||
* field of the pcapng IDB. The field is in units of 16 bits,
|
||||
* i.e. 1 means 16 bits of FCS, 2 means 32 bits of FCS, etc..
|
||||
*
|
||||
* A reserved bit, which must be zero.
|
||||
*
|
||||
* An "FCS length present" flag; if 0, the "FCS length" field
|
||||
* should be ignored, and if 1, the "FCS length" field should
|
||||
* be used.
|
||||
*
|
||||
* 10 reserved bits, which must be zero. They were originally
|
||||
* intended to be used as a "class" field, allowing additional
|
||||
* classes of link-layer types to be defined, with a class value
|
||||
* of 0 indicating that the link-layer type is a LINKTYPE_ value.
|
||||
* A value of 0x224 was, at one point, used by NetBSD to define
|
||||
* "raw" packet types, with the lower 16 bits containing a
|
||||
* NetBSD AF_ value; see
|
||||
*
|
||||
* https://marc.info/?l=tcpdump-workers&m=98296750229149&w=2
|
||||
*
|
||||
* It's unknown whether those were ever used in capture files,
|
||||
* or if the intent was just to use it as a link-layer type
|
||||
* for BPF programs; NetBSD's libpcap used to support them in
|
||||
* the BPF code generator, but it no longer does so. If it
|
||||
* was ever used in capture files, or if classes other than
|
||||
* "LINKTYPE_ value" are ever useful in capture files, we could
|
||||
* re-enable this, and use the reserved 16 bits following the
|
||||
* link-layer type in pcapng files to hold the class information
|
||||
* there. (Note, BTW, that LINKTYPE_RAW/DLT_RAW is now being
|
||||
* interpreted by libpcap, tcpdump, and Wireshark as "raw IP",
|
||||
* including both IPv4 and IPv6, with the version number in the
|
||||
* header being checked to see which it is, not just "raw IPv4";
|
||||
* there are LINKTYPE_IPV4/DLT_IPV4 and LINKTYPE_IPV6/DLT_IPV6
|
||||
* values if "these are IPv{4,6} and only IPv{4,6} packets"
|
||||
* types are needed.)
|
||||
*/
|
||||
#define LT_LINKTYPE(x) ((x) & 0x0000FFFF)
|
||||
#define LT_CLASS(x) (((x) & 0x3FFF0000) >> 16)
|
||||
#define LT_CLASS_LINKTYPE 0x0000
|
||||
#define LT_FCS_LENGTH_PRESENT(x) ((x) & 0x04000000)
|
||||
#define LT_FCS_LENGTH(x) (((x) & 0xF0000000) >> 28)
|
||||
#define LT_FCS_DATALINK_EXT(x) (((x) & 0xF) << 28) | 0x04000000)
|
||||
|
||||
/*
|
||||
* Private file type/subtype values; pcap and nanosecond-resolution
|
||||
* pcap are imported from wiretap/file_access.c.
|
||||
|
@ -359,51 +416,44 @@ wtap_open_return_val libpcap_open(wtap *wth, int *err, gchar **err_info)
|
|||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Map the "network" field from the header to a Wiretap
|
||||
* encapsulation.
|
||||
*
|
||||
* Link-layer header types are assigned for both pcap and
|
||||
* pcapng, and the same value must work with both. In pcapng,
|
||||
* the link-layer header type field in an Interface Description
|
||||
* Block is 16 bits, so only the bottommost 16 bits of the
|
||||
* link-layer header type in a pcap file can be used for the
|
||||
* header type value.
|
||||
*
|
||||
* In libpcap, the upper 16 bits are divided into:
|
||||
*
|
||||
* A "class" field, to support non-standard link-layer
|
||||
* header types; class 0 is for standard header types,
|
||||
* class 0x224 was reserved for a NetBSD feature, and
|
||||
* all other class values are reserved. That is in the
|
||||
* lower 10 bits of the upper 16 bits.
|
||||
*
|
||||
* An "FCS length" field, to allow the FCS length to
|
||||
* be specified, just as it can be specified in the
|
||||
* if_fcslen field of the pcapng IDB. That is in the
|
||||
* topmost 4 bits of the upper 16 bits. The field is
|
||||
* in units of 16 bits, i.e. 1 means 16 bits of FCS,
|
||||
* 2 means 32 bits of FCS, etc..
|
||||
*
|
||||
* An "FCS length present" flag; if 0, the "FCS length"
|
||||
* field should be ignored, and if 1, the "FCS length"
|
||||
* field should be used. That is in the bit just above
|
||||
* the "class" field.
|
||||
*
|
||||
* The one remaining bit is reserved.
|
||||
*
|
||||
* We ignore the FCS information and reserved bit; we include
|
||||
* the "class" field, in case there's ever a need to implement
|
||||
* it - currently, any link-layer header type with a non-zero
|
||||
* class value will fail.
|
||||
* Check the "class" field of the "network" field in the header.
|
||||
*/
|
||||
wth->file_encap = wtap_pcap_encap_to_wtap_encap(hdr.network & 0x03FFFFFF);
|
||||
if (wth->file_encap == WTAP_ENCAP_UNKNOWN) {
|
||||
switch (LT_CLASS(hdr.network)) {
|
||||
|
||||
case LT_CLASS_LINKTYPE:
|
||||
/*
|
||||
* Map the link-layer type from the "network" field in
|
||||
* the header to a Wiretap encapsulation.
|
||||
*/
|
||||
wth->file_encap = wtap_pcap_encap_to_wtap_encap(LT_LINKTYPE(hdr.network));
|
||||
if (wth->file_encap == WTAP_ENCAP_UNKNOWN) {
|
||||
*err = WTAP_ERR_UNSUPPORTED;
|
||||
*err_info = ws_strdup_printf("pcap: network type %u unknown or unsupported",
|
||||
hdr.network);
|
||||
return WTAP_OPEN_ERROR;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
*err = WTAP_ERR_UNSUPPORTED;
|
||||
*err_info = ws_strdup_printf("pcap: network type %u unknown or unsupported",
|
||||
hdr.network);
|
||||
*err_info = ws_strdup_printf("pcap: network type class 0x%04x not supported",
|
||||
LT_CLASS(hdr.network));
|
||||
return WTAP_OPEN_ERROR;
|
||||
}
|
||||
|
||||
/*
|
||||
* Extract the FCS information, if present.
|
||||
*/
|
||||
libpcap->fcs_len = -1;
|
||||
if (LT_FCS_LENGTH_PRESENT(hdr.network)) {
|
||||
/*
|
||||
* We have an FCS length.
|
||||
*/
|
||||
libpcap->fcs_len = LT_FCS_LENGTH(hdr.network) * 16;
|
||||
}
|
||||
|
||||
libpcap->encap_priv = NULL;
|
||||
|
||||
/*
|
||||
|
@ -967,7 +1017,7 @@ libpcap_read_packet(wtap *wth, FILE_T fh, wtap_rec *rec,
|
|||
return FALSE; /* failed */
|
||||
|
||||
pcap_read_post_process(is_nokia, wth->file_encap, rec,
|
||||
ws_buffer_start_ptr(buf), libpcap->byte_swapped, -1);
|
||||
ws_buffer_start_ptr(buf), libpcap->byte_swapped, libpcap->fcs_len);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue