+ if ((header->type & 0x7f) == TYPE_PAD) {
+ continue;
+ }
+
+ num_ext_hdr = dag_erf_ext_header_count(dp, rlen);
+
+ /* ERF encapsulation */
+ /* The Extensible Record Format is not dropped for this kind of encapsulation,
+ * and will be handled as a pseudo header by the decoding application.
+ * The information carried in the ERF header and in the optional subheader (if present)
+ * could be merged with the libpcap information, to offer a better decoding.
+ * The packet length is
+ * o the length of the packet on the link (header->wlen),
+ * o plus the length of the ERF header (dag_record_size), as the length of the
+ * pseudo header will be adjusted during the decoding,
+ * o plus the length of the optional subheader (if present).
+ *
+ * The capture length is header.rlen and the byte stuffing for alignment will be dropped
+ * if the capture length is greater than the packet length.
+ */
+ if (p->linktype == DLT_ERF) {
+ packet_len = ntohs(header->wlen) + dag_record_size;
+ caplen = rlen;
+ switch ((header->type & 0x7f)) {
+ case TYPE_MC_AAL5:
+ case TYPE_MC_ATM:
+ case TYPE_MC_HDLC:
+ case TYPE_MC_RAW_CHANNEL:
+ case TYPE_MC_RAW:
+ case TYPE_MC_AAL2:
+ case TYPE_COLOR_MC_HDLC_POS:
+ packet_len += 4; /* MC header */
+ break;
+
+ case TYPE_COLOR_HASH_ETH:
+ case TYPE_DSM_COLOR_ETH:
+ case TYPE_COLOR_ETH:
+ case TYPE_ETH:
+ packet_len += 2; /* ETH header */
+ break;
+ } /* switch type */
+
+ /* Include ERF extension headers */
+ packet_len += (8 * num_ext_hdr);
+
+ if (caplen > packet_len) {
+ caplen = packet_len;
+ }
+ } else {
+ /* Other kind of encapsulation according to the header Type */
+
+ /* Skip over generic ERF header */
+ dp += dag_record_size;
+ /* Skip over extension headers */
+ dp += 8 * num_ext_hdr;
+
+ switch((header->type & 0x7f)) {
+ case TYPE_ATM:
+ case TYPE_AAL5:
+ if (header->type == TYPE_AAL5) {
+ packet_len = ntohs(header->wlen);
+ caplen = rlen - dag_record_size;
+ }
+ case TYPE_MC_ATM:
+ if (header->type == TYPE_MC_ATM) {
+ caplen = packet_len = ATM_CELL_SIZE;
+ dp+=4;
+ }
+ case TYPE_MC_AAL5:
+ if (header->type == TYPE_MC_AAL5) {
+ packet_len = ntohs(header->wlen);
+ caplen = rlen - dag_record_size - 4;
+ dp+=4;
+ }
+ /* Skip over extension headers */
+ caplen -= (8 * num_ext_hdr);
+
+ if (header->type == TYPE_ATM) {
+ caplen = packet_len = ATM_CELL_SIZE;
+ }
+ if (p->linktype == DLT_SUNATM) {
+ struct sunatm_hdr *sunatm = (struct sunatm_hdr *)dp;
+ unsigned long rawatm;
+
+ rawatm = ntohl(*((unsigned long *)dp));
+ sunatm->vci = htons((rawatm >> 4) & 0xffff);
+ sunatm->vpi = (rawatm >> 20) & 0x00ff;
+ sunatm->flags = ((header->flags.iface & 1) ? 0x80 : 0x00) |
+ ((sunatm->vpi == 0 && sunatm->vci == htons(5)) ? 6 :
+ ((sunatm->vpi == 0 && sunatm->vci == htons(16)) ? 5 :
+ ((dp[ATM_HDR_SIZE] == 0xaa &&
+ dp[ATM_HDR_SIZE+1] == 0xaa &&
+ dp[ATM_HDR_SIZE+2] == 0x03) ? 2 : 1)));
+
+ } else {
+ packet_len -= ATM_HDR_SIZE;
+ caplen -= ATM_HDR_SIZE;
+ dp += ATM_HDR_SIZE;
+ }
+ break;
+
+ case TYPE_COLOR_HASH_ETH:
+ case TYPE_DSM_COLOR_ETH:
+ case TYPE_COLOR_ETH:
+ case TYPE_ETH:
+ packet_len = ntohs(header->wlen);
+ packet_len -= (pd->dag_fcs_bits >> 3);
+ caplen = rlen - dag_record_size - 2;
+ /* Skip over extension headers */
+ caplen -= (8 * num_ext_hdr);
+ if (caplen > packet_len) {
+ caplen = packet_len;
+ }
+ dp += 2;
+ break;
+
+ case TYPE_COLOR_HASH_POS:
+ case TYPE_DSM_COLOR_HDLC_POS:
+ case TYPE_COLOR_HDLC_POS:
+ case TYPE_HDLC_POS:
+ packet_len = ntohs(header->wlen);
+ packet_len -= (pd->dag_fcs_bits >> 3);
+ caplen = rlen - dag_record_size;
+ /* Skip over extension headers */
+ caplen -= (8 * num_ext_hdr);
+ if (caplen > packet_len) {
+ caplen = packet_len;
+ }
+ break;
+
+ case TYPE_COLOR_MC_HDLC_POS:
+ case TYPE_MC_HDLC:
+ packet_len = ntohs(header->wlen);
+ packet_len -= (pd->dag_fcs_bits >> 3);
+ caplen = rlen - dag_record_size - 4;
+ /* Skip over extension headers */
+ caplen -= (8 * num_ext_hdr);
+ if (caplen > packet_len) {
+ caplen = packet_len;
+ }
+ /* jump the MC_HDLC_HEADER */
+ dp += 4;
+#ifdef DLT_MTP2_WITH_PHDR
+ if (p->linktype == DLT_MTP2_WITH_PHDR) {
+ /* Add the MTP2 Pseudo Header */
+ caplen += MTP2_HDR_LEN;
+ packet_len += MTP2_HDR_LEN;
+
+ TempPkt[MTP2_SENT_OFFSET] = 0;
+ TempPkt[MTP2_ANNEX_A_USED_OFFSET] = MTP2_ANNEX_A_USED_UNKNOWN;
+ *(TempPkt+MTP2_LINK_NUMBER_OFFSET) = ((header->rec.mc_hdlc.mc_header>>16)&0x01);
+ *(TempPkt+MTP2_LINK_NUMBER_OFFSET+1) = ((header->rec.mc_hdlc.mc_header>>24)&0xff);
+ memcpy(TempPkt+MTP2_HDR_LEN, dp, caplen);
+ dp = TempPkt;
+ }
+#endif
+ break;
+
+ case TYPE_IPV4:
+ case TYPE_IPV6:
+ packet_len = ntohs(header->wlen);
+ caplen = rlen - dag_record_size;
+ /* Skip over extension headers */
+ caplen -= (8 * num_ext_hdr);
+ if (caplen > packet_len) {
+ caplen = packet_len;
+ }
+ break;
+
+ /* These types have no matching 'native' DLT, but can be used with DLT_ERF above */
+ case TYPE_MC_RAW:
+ case TYPE_MC_RAW_CHANNEL:
+ case TYPE_IP_COUNTER:
+ case TYPE_TCP_FLOW_COUNTER:
+ case TYPE_INFINIBAND:
+ case TYPE_RAW_LINK:
+ case TYPE_INFINIBAND_LINK:
+ default:
+ /* Unhandled ERF type.
+ * Ignore rather than generating error
+ */
+ continue;
+ } /* switch type */
+
+ } /* ERF encapsulation */
+
+ if (caplen > p->snapshot)
+ caplen = p->snapshot;
+