Handle ETH_P_CANFD as well as ETH_P_CAN.
[metze/wireshark/wip.git] / wiretap / pcap-common.c
index 263af672fedcc4b8206d2b65436c9eada5ca61f2..27e3fd687f5939d88ef4185d9817db80ef55d103 100644 (file)
@@ -206,7 +206,7 @@ static const struct {
        { 105,          WTAP_ENCAP_IEEE_802_11 }, /* IEEE 802.11 */
        { 106,          WTAP_ENCAP_LINUX_ATM_CLIP },
        { 107,          WTAP_ENCAP_FRELAY },    /* Frame Relay */
-       { 108,          WTAP_ENCAP_NULL },      /* OpenBSD loopback */
+       { 108,          WTAP_ENCAP_LOOP },      /* OpenBSD loopback */
        { 109,          WTAP_ENCAP_ENC },       /* OpenBSD IPSEC enc */
 #if 0
        { 110,          WTAP_ENCAP_LANE_802_3 },/* ATM LANE 802.3 */
@@ -306,10 +306,9 @@ static const struct {
 
        { 169,          WTAP_ENCAP_GPRS_LLC },
 
-       /*
-        * 170 and 171 are reserved for ITU-T G.7041/Y.1303 Generic
-        * Framing Procedure.
-        */
+       /* ITU-T G.7041/Y.1303 Generic Framing Procedure. */
+       { 170,          WTAP_ENCAP_GFP_T },
+       { 171,          WTAP_ENCAP_GFP_F },
 
        /* Registered by Gcom, Inc. */
        { 172,          WTAP_ENCAP_GCOM_TIE1 },
@@ -327,8 +326,10 @@ static const struct {
        { 181,          WTAP_ENCAP_JUNIPER_CHDLC },
        /* VOIP Frames prepended with meta-information */
        { 183,          WTAP_ENCAP_JUNIPER_VP },
-       /* raw USB packets */
-       { 186,          WTAP_ENCAP_USB },
+       /* Virtual Network Frames prepended with meta-information */
+       { 184,          WTAP_ENCAP_JUNIPER_VN },
+       /* USB packets from FreeBSD's USB BPF tap */
+       { 186,          WTAP_ENCAP_USB_FREEBSD },
        /* Bluetooth HCI UART transport (part H:4) frames, like hcidump */
        { 187,          WTAP_ENCAP_BLUETOOTH_H4 },
        /* IEEE 802.16 MAC Common Part Sublayer */
@@ -400,7 +401,7 @@ static const struct {
        /* netANALYZER pseudo-header in transparent mode */
        { 241,          WTAP_ENCAP_NETANALYZER_TRANSPARENT },
        /* IP-over-Infiniband, as specified by RFC 4391 section 6 */
-       { 242,          WTAP_ENCAP_IP_OVER_IB },
+       { 242,          WTAP_ENCAP_IP_OVER_IB_PCAP },
        /* ISO/IEC 13818-1 MPEG2-TS packets */
        { 243,          WTAP_ENCAP_MPEG_2_TS },
        /* NFC LLCP */
@@ -433,6 +434,9 @@ static const struct {
        /* IPMI Trace Data Collection */
        { 260,          WTAP_ENCAP_IPMI_TRACE },
 
+       /* ISO14443 contactless smartcard standards */
+       { 264,          WTAP_ENCAP_ISO14443 },
+
        /*
         * To repeat:
         *
@@ -463,25 +467,11 @@ static const struct {
        /*
         * 11 is DLT_ATM_RFC1483 on most platforms; the only libpcaps I've
         * seen that define anything other than DLT_ATM_RFC1483 as 11 are
-        * the BSD/OS one, which defines DLT_FR as 11, and libpcap 0.5,
-        * which define it as 100, mapping the kernel's value to 100, in
-        * an attempt to hide the different values used on different
+        * the BSD/OS one, which defines DLT_FR as 11.  We handle it as
+        * Frame Relay on BSD/OS and LLC-encapsulated ATM on all other
         * platforms.
-        *
-        * If this is a platform where DLT_FR is defined as 11, we
-        * don't handle 11 at all; otherwise, we handle it as
-        * DLT_ATM_RFC1483 (this means we'd misinterpret Frame Relay
-        * captures from BSD/OS if running on platforms other than BSD/OS,
-        * but
-        *
-        *      1) we don't yet support DLT_FR
-        *
-        * and
-        *
-        *      2) nothing short of a heuristic would let us interpret
-        *         them correctly).
         */
-#if defined(DLT_FR) && (DLT_FR == 11)
+#if defined(__bsdi__) /* BSD/OS */
        { 11,           WTAP_ENCAP_FRELAY },
 #else
        { 11,           WTAP_ENCAP_ATM_RFC1483 },
@@ -495,13 +485,13 @@ static const struct {
         * (it's just like DLT_NULL, only with the AF_ value in network
         * rather than host byte order - Wireshark figures out the
         * byte order from the data, so we don't care what byte order
-        * it's in), so if DLT_LOOP is defined as 12, interpret 12
-        * as WTAP_ENCAP_NULL, otherwise, unless DLT_C_HDLC is defined
-        * as 12, interpret it as WTAP_ENCAP_RAW_IP.
+        * it's in), so, on OpenBSD, interpret 12 as WTAP_ENCAP_LOOP,
+        * otherwise, if we're not on BSD/OS, interpret it as
+        * WTAP_ENCAP_RAW_IP.
         */
-#if defined(DLT_LOOP) && (DLT_LOOP == 12)
-       { 12,           WTAP_ENCAP_NULL },
-#elif defined(DLT_C_HDLC) && (DLT_C_HDLC == 12)
+#if defined(__OpenBSD__)
+       { 12,           WTAP_ENCAP_LOOP },
+#elif defined(__bsdi__) /* BSD/OS */
        /*
         * Put entry for Cisco HDLC here.
         * XXX - is this just WTAP_ENCAP_CHDLC, i.e. does the frame
@@ -532,7 +522,7 @@ static const struct {
         * treate 13 as WTAP_ENCAP_ATM_RFC1483, but, on all other
         * systems, we can read OpenBSD DLT_ENC captures.
         */
-#if defined(DLT_ATM_RFC1483) && (DLT_ATM_RFC1483 == 13)
+#if defined(__bsdi__) /* BSD/OS */
        { 13,           WTAP_ENCAP_ATM_RFC1483 },
 #else
        { 13,           WTAP_ENCAP_ENC },
@@ -581,21 +571,24 @@ static const struct {
         *      DLT_I4L_IP with the ISDN4Linux patches for libpcap
         *      (and on SuSE 6.3).
         */
-#if defined(DLT_CIP) && (DLT_CIP == 16)
-       { 16,           WTAP_ENCAP_LINUX_ATM_CLIP },
-#endif
-#if defined(DLT_HDLC) && (DLT_HDLC == 16)
+#if defined(__NetBSD__)
        { 16,           WTAP_ENCAP_CHDLC },
+#elif !defined(__bsdi__)
+       /*
+        * If you care about the two different Linux interpretations
+        * of 16, fix it yourself.
+        */
+       { 16,           WTAP_ENCAP_LINUX_ATM_CLIP },
 #endif
 
        /*
         * 17 is DLT_LANE8023 in SuSE 6.3 libpcap; we don't currently
         * handle it.
         * It is also used as the PF (Packet Filter) logging format beginning
-        * with OpenBSD 3.0; we use 17 for PF logs unless DLT_LANE8023 is
-        * defined with the value 17.
+        * with OpenBSD 3.0; we use 17 for PF logs on OpenBSD and don't
+        * use it otherwise.
         */
-#if !defined(DLT_LANE8023) || (DLT_LANE8023 != 17)
+#if defined(__OpenBSD__)
        { 17,           WTAP_ENCAP_OLD_PFLOG },
 #endif
 
@@ -701,19 +694,21 @@ wtap_wtap_encap_to_pcap_encap(int encap)
 }
 
 gboolean
-wtap_encap_requires_phdr(int encap) {
-       if (
-               (encap == WTAP_ENCAP_ATM_PDUS) ||
-               (encap == WTAP_ENCAP_IRDA) ||
-               (encap == WTAP_ENCAP_MTP2_WITH_PHDR) ||
-               (encap == WTAP_ENCAP_LINUX_LAPD) ||
-               (encap == WTAP_ENCAP_SITA) ||
-               (encap == WTAP_ENCAP_ERF) ||
-               (encap == WTAP_ENCAP_I2C) ||
-               (encap == WTAP_ENCAP_BLUETOOTH_H4_WITH_PHDR) ||
-               (encap == WTAP_ENCAP_BLUETOOTH_LINUX_MONITOR) ||
-               (encap == WTAP_ENCAP_PPP_WITH_PHDR)
-       ) {
+wtap_encap_requires_phdr(int wtap_encap)
+{
+       switch (wtap_encap) {
+
+       case WTAP_ENCAP_ATM_PDUS:
+       case WTAP_ENCAP_IRDA:
+       case WTAP_ENCAP_MTP2_WITH_PHDR:
+       case WTAP_ENCAP_LINUX_LAPD:
+       case WTAP_ENCAP_SITA:
+       case WTAP_ENCAP_BLUETOOTH_H4_WITH_PHDR:
+       case WTAP_ENCAP_BLUETOOTH_LINUX_MONITOR:
+       case WTAP_ENCAP_NFC_LLCP:
+       case WTAP_ENCAP_PPP_WITH_PHDR:
+       case WTAP_ENCAP_ERF:
+       case WTAP_ENCAP_I2C:
                return TRUE;
        }
        return FALSE;
@@ -749,6 +744,18 @@ wtap_encap_requires_phdr(int encap) {
  */
 #define NOKIA_LEN      4       /* length of the header */
 
+/*
+ * The fake link-layer header of Linux cooked packets.
+ */
+#define LINUX_SLL_PROTOCOL_OFFSET      14      /* protocol */
+#define LINUX_SLL_LEN                  16      /* length of the header */
+
+/*
+ * The protocols we have to check for.
+ */
+#define LINUX_SLL_P_CAN                        0x000C  /* Controller Area Network */
+#define LINUX_SLL_P_CANFD              0x000D  /* Controller Area Network flexible data rate */
+
 /*
  * The fake link-layer header of IrDA packets as introduced by Jean Tourrilhes
  * to libpcap.
@@ -1141,7 +1148,6 @@ struct usb_device_setup_hdr {
        guint16 wLength;
 };
 
-
 /*
  * Offset of the *end* of a field within a particular structure.
  */
@@ -1176,6 +1182,57 @@ struct usb_device_setup_hdr {
                PBSWAP64((guint8 *)fieldp); \
        }
 
+struct can_socketcan_hdr {
+       guint32 can_id;                 /* CAN ID and flags */
+       guint8 payload_length;          /* Frame payload length */
+       guint8 padding;
+       guint8 reserved1;
+       guint8 reserved2;
+};
+
+static void
+pcap_byteswap_linux_sll_pseudoheader(struct wtap_pkthdr *phdr, guint8 *pd)
+{
+       guint packet_size;
+       guint16 protocol;
+       struct can_socketcan_hdr *can_socketcan_phdr;
+
+       /*
+        * Minimum of captured and actual length (just in case the
+        * actual length < the captured length, which Should Never
+        * Happen).
+        */
+       packet_size = phdr->caplen;
+       if (packet_size > phdr->len)
+               packet_size = phdr->len;
+
+       if (packet_size < LINUX_SLL_LEN) {
+               /* Not enough data to have the protocol */
+               return;
+       }
+
+       protocol = pntoh16(&pd[LINUX_SLL_PROTOCOL_OFFSET]);
+       if (protocol != LINUX_SLL_P_CAN && protocol != LINUX_SLL_P_CANFD) {
+               /* Not a CAN packet; nothing to fix */
+               return;
+       }
+
+       /*
+        * Greasy hack, but we never directly dereference any of
+        * the fields in *can_socketcan_phdr, we just get offsets
+        * of and addresses of its members and byte-swap it with a
+        * byte-at-a-time macro, so it's alignment-safe.
+        */
+       can_socketcan_phdr = (struct can_socketcan_hdr *)(void *)(pd + LINUX_SLL_LEN);
+
+       if (packet_size < LINUX_SLL_LEN + sizeof(can_socketcan_phdr->can_id)) {
+               /* Not enough data to have the full CAN ID */
+               return;
+       }
+
+       PBSWAP32((guint8 *)&can_socketcan_phdr->can_id);
+}
+
 static void
 pcap_byteswap_linux_usb_pseudoheader(struct wtap_pkthdr *phdr, guint8 *pd,
     gboolean header_len_64_bytes)
@@ -1295,7 +1352,7 @@ pcap_byteswap_nflog_pseudoheader(struct wtap_pkthdr *phdr, guint8 *pd)
 
        p = pd;
        nfhdr = (struct nflog_hdr *)pd;
-       if (!(nfhdr->nflog_version) == 0) {
+       if (nfhdr->nflog_version != 0) {
                /* Unknown NFLOG version */
                return;
        }
@@ -1333,6 +1390,17 @@ pcap_byteswap_nflog_pseudoheader(struct wtap_pkthdr *phdr, guint8 *pd)
        }
 }
 
+/*
+ * Pseudo-header at the beginning of DLT_BLUETOOTH_HCI_H4_WITH_PHDR frames.
+ * Values in network byte order.
+ */
+struct libpcap_bt_phdr {
+       guint32 direction;     /* Bit 0 hold the frame direction. */
+};
+
+#define LIBPCAP_BT_PHDR_SENT    0
+#define LIBPCAP_BT_PHDR_RECV    1
+
 static gboolean
 pcap_read_bt_pseudoheader(FILE_T fh,
     union wtap_pseudo_header *pseudo_header, int *err, gchar **err_info)
@@ -1346,6 +1414,15 @@ pcap_read_bt_pseudoheader(FILE_T fh,
        return TRUE;
 }
 
+/*
+ * Pseudo-header at the beginning of DLT_BLUETOOTH_LINUX_MONITOR frames.
+ * Values in network byte order.
+ */
+struct libpcap_bt_monitor_phdr {
+       guint16 adapter_id;
+       guint16 opcode;
+};
+
 static gboolean
 pcap_read_bt_monitor_pseudoheader(FILE_T fh,
     union wtap_pseudo_header *pseudo_header, int *err, gchar **err_info)
@@ -1374,6 +1451,16 @@ pcap_read_llcp_pseudoheader(FILE_T fh,
        return TRUE;
 }
 
+/*
+ * Pseudo-header at the beginning of DLT_PPP_WITH_DIR frames.
+ */
+struct libpcap_ppp_phdr {
+       guint8 direction;
+};
+
+#define LIBPCAP_PPP_PHDR_RECV    0
+#define LIBPCAP_PPP_PHDR_SENT    1
+
 static gboolean
 pcap_read_ppp_pseudoheader(FILE_T fh,
     union wtap_pseudo_header *pseudo_header, int *err, gchar **err_info)
@@ -1472,13 +1559,21 @@ pcap_read_erf_subheader(FILE_T fh, union wtap_pseudo_header *pseudo_header,
                pseudo_header->erf.subhdr.mc_hdr = pntoh32(&erf_subhdr[0]);
                *psize = sizeof(erf_mc_header_t);
                break;
+       case ERF_TYPE_AAL2:
+               /* Extract the AAL2 header to include it in the pseudo header part */
+               if (!wtap_read_bytes(fh, erf_subhdr, sizeof(erf_aal2_header_t), err, err_info))
+                       return FALSE;
+               pseudo_header->erf.subhdr.aal2_hdr = pntoh32(&erf_subhdr[0]);
+               *psize = sizeof(erf_aal2_header_t);
+               break;
        case ERF_TYPE_ETH:
        case ERF_TYPE_COLOR_ETH:
        case ERF_TYPE_DSM_COLOR_ETH:
+       case ERF_TYPE_COLOR_HASH_ETH:
                /* Extract the Ethernet additional header to include it in the pseudo header part */
                if (!wtap_read_bytes(fh, erf_subhdr, sizeof(erf_eth_header_t), err, err_info))
                        return FALSE;
-               pseudo_header->erf.subhdr.eth_hdr = pntoh16(&erf_subhdr[0]);
+               memcpy(&pseudo_header->erf.subhdr.eth_hdr, erf_subhdr, sizeof pseudo_header->erf.subhdr.eth_hdr);
                *psize = sizeof(erf_eth_header_t);
                break;
        default:
@@ -1583,9 +1678,10 @@ pcap_process_pseudo_header(FILE_T fh, int file_type, int wtap_encap,
                 * XXX - in pcap-ng, there *could* be a packet option
                 * indicating the FCS length.
                 */
-               phdr->pseudo_header.ieee_802_11.presence_flags = 0; /* absent or supplied in the packet data */
+               memset(&phdr->pseudo_header.ieee_802_11, 0, sizeof(phdr->pseudo_header.ieee_802_11));
                phdr->pseudo_header.ieee_802_11.fcs_len = -1;
                phdr->pseudo_header.ieee_802_11.decrypted = FALSE;
+               phdr->pseudo_header.ieee_802_11.datapad = FALSE;
                break;
 
        case WTAP_ENCAP_IRDA:
@@ -1706,7 +1802,7 @@ pcap_process_pseudo_header(FILE_T fh, int file_type, int wtap_encap,
        case WTAP_ENCAP_NFC_LLCP:
                if (check_packet_size && packet_size < LLCP_HEADER_LEN) {
                        *err = WTAP_ERR_BAD_FILE;
-                       *err_info = g_strdup_printf("pcap: libpcap llcp file too short");
+                       *err_info = g_strdup("pcap: libpcap llcp file too short");
                        return -1;
                }
                if (!pcap_read_llcp_pseudoheader(fh, &phdr->pseudo_header, err, err_info))
@@ -1837,6 +1933,11 @@ pcap_read_post_process(int file_type, int wtap_encap,
                phdr->pseudo_header.eth.fcs_len = fcs_len;
                break;
 
+       case WTAP_ENCAP_SLL:
+               if (bytes_swapped)
+                       pcap_byteswap_linux_sll_pseudoheader(phdr, pd);
+               break;
+
        case WTAP_ENCAP_USB_LINUX:
                if (bytes_swapped)
                        pcap_byteswap_linux_usb_pseudoheader(phdr, pd, FALSE);
@@ -1861,6 +1962,16 @@ pcap_read_post_process(int file_type, int wtap_encap,
                        pcap_byteswap_nflog_pseudoheader(phdr, pd);
                break;
 
+       case WTAP_ENCAP_ERF:
+               /*
+                * Update packet size to account for ERF padding and snapping.
+                * Captured length is minimum of wlen and previously calculated
+                * caplen (which would have included padding but not phdr).
+                */
+               phdr->len = phdr->pseudo_header.erf.phdr.wlen;
+               phdr->caplen = MIN(phdr->len, phdr->caplen);
+               break;
+
        default:
                break;
        }
@@ -1906,10 +2017,14 @@ pcap_get_phdr_size(int encap, const union wtap_pseudo_header *pseudo_header)
                case ERF_TYPE_COLOR_MC_HDLC_POS:
                        hdrsize += (int)sizeof(struct erf_mc_hdr);
                        break;
+               case ERF_TYPE_AAL2:
+                       hdrsize += (int)sizeof(struct erf_aal2_hdr);
+                       break;
 
                case ERF_TYPE_ETH:
                case ERF_TYPE_COLOR_ETH:
                case ERF_TYPE_DSM_COLOR_ETH:
+               case ERF_TYPE_COLOR_HASH_ETH:
                        hdrsize += (int)sizeof(struct erf_eth_hdr);
                        break;
 
@@ -1968,11 +2083,13 @@ pcap_write_phdr(wtap_dumper *wdh, int encap, const union wtap_pseudo_header *pse
        guint8 mtp2_hdr[MTP2_HDR_LEN];
        guint8 sita_hdr[SITA_HDR_LEN];
        guint8 erf_hdr[ sizeof(struct erf_mc_phdr)];
+       guint8 erf_subhdr[sizeof(union erf_subhdr)];
        struct i2c_file_hdr i2c_hdr;
        struct libpcap_bt_phdr bt_hdr;
        struct libpcap_bt_monitor_phdr bt_monitor_hdr;
        struct libpcap_ppp_phdr ppp_hdr;
        size_t size;
+       size_t subhdr_size = 0;
 
        switch (encap) {
 
@@ -2081,7 +2198,17 @@ pcap_write_phdr(wtap_dumper *wdh, int encap, const union wtap_pseudo_header *pse
                phtolell(&erf_hdr[0], pseudo_header->erf.phdr.ts);
                erf_hdr[8] = pseudo_header->erf.phdr.type;
                erf_hdr[9] = pseudo_header->erf.phdr.flags;
-               phtons(&erf_hdr[10], pseudo_header->erf.phdr.rlen);
+
+               /*
+                * Recalculate rlen as padding (and maybe extension headers)
+                * have been stripped from caplen.
+                *
+                * XXX: Since we don't have phdr->caplen here, assume caplen was
+                * calculated correctly and recalculate from wlen.
+                */
+               phtons(&erf_hdr[10],
+                       MIN(pseudo_header->erf.phdr.rlen, pseudo_header->erf.phdr.wlen + pcap_get_phdr_size(WTAP_ENCAP_ERF, pseudo_header)));
+
                phtons(&erf_hdr[12], pseudo_header->erf.phdr.lctr);
                phtons(&erf_hdr[14], pseudo_header->erf.phdr.wlen);
                size = sizeof(struct erf_phdr);
@@ -2094,14 +2221,19 @@ pcap_write_phdr(wtap_dumper *wdh, int encap, const union wtap_pseudo_header *pse
                case ERF_TYPE_MC_AAL5:
                case ERF_TYPE_MC_AAL2:
                case ERF_TYPE_COLOR_MC_HDLC_POS:
-                       phtonl(&erf_hdr[16], pseudo_header->erf.subhdr.mc_hdr);
-                       size += (int)sizeof(struct erf_mc_hdr);
+                       phtonl(&erf_subhdr[0], pseudo_header->erf.subhdr.mc_hdr);
+                       subhdr_size += (int)sizeof(struct erf_mc_hdr);
+                       break;
+               case ERF_TYPE_AAL2:
+                       phtonl(&erf_subhdr[0], pseudo_header->erf.subhdr.aal2_hdr);
+                       subhdr_size += (int)sizeof(struct erf_aal2_hdr);
                        break;
                case ERF_TYPE_ETH:
                case ERF_TYPE_COLOR_ETH:
                case ERF_TYPE_DSM_COLOR_ETH:
-                       phtons(&erf_hdr[16], pseudo_header->erf.subhdr.eth_hdr);
-                       size += (int)sizeof(struct erf_eth_hdr);
+               case ERF_TYPE_COLOR_HASH_ETH:
+                       memcpy(&erf_subhdr[0], &pseudo_header->erf.subhdr.eth_hdr, sizeof pseudo_header->erf.subhdr.eth_hdr);
+                       subhdr_size += (int)sizeof(struct erf_eth_hdr);
                        break;
                default:
                        break;
@@ -2121,12 +2253,23 @@ pcap_write_phdr(wtap_dumper *wdh, int encap, const union wtap_pseudo_header *pse
                        do {
                                phtonll(erf_exhdr, pseudo_header->erf.ehdr_list[i].ehdr);
                                type = erf_exhdr[0];
+                               /* Clear more extension headers bit if > 8 */
+                               if(i == max-1)
+                                       erf_exhdr[0] = erf_exhdr[0] & 0x7F;
+
                                if (!wtap_dump_file_write(wdh, erf_exhdr, 8, err))
                                        return FALSE;
                                wdh->bytes_dumped += 8;
                                i++;
                        } while (type & 0x80 && i < max);
                }
+
+               /*
+                * Now write out the subheader.
+                */
+               if(!wtap_dump_file_write(wdh, erf_subhdr, subhdr_size, err))
+                       return FALSE;
+               wdh->bytes_dumped += subhdr_size;
                break;
 
        case WTAP_ENCAP_I2C: