void capture_ap1394(const guchar *pd, int offset, int len, packet_counts *ld) { guint16 etype; if (!BYTES_ARE_IN_FRAME(offset, len, 18)) { ld->other++; return; } /* Skip destination and source addresses */ offset += 16; etype = pntohs(&pd[offset]); offset += 2; capture_ethertype(etype, pd, offset, len, ld); }
void capture_fddi(const guchar *pd, int len, packet_counts *ld) { int offset = 0, fc; if (!BYTES_ARE_IN_FRAME(0, len, FDDI_HEADER_SIZE + FDDI_PADDING)) { ld->other++; return; } offset = FDDI_PADDING + FDDI_HEADER_SIZE; fc = (int) pd[FDDI_P_FC+FDDI_PADDING]; switch (fc) { /* From now, only 802.2 SNAP (Async. LCC frame) is supported */ case FDDI_FC_LLC_ASYNC + 0 : case FDDI_FC_LLC_ASYNC + 1 : case FDDI_FC_LLC_ASYNC + 2 : case FDDI_FC_LLC_ASYNC + 3 : case FDDI_FC_LLC_ASYNC + 4 : case FDDI_FC_LLC_ASYNC + 5 : case FDDI_FC_LLC_ASYNC + 6 : case FDDI_FC_LLC_ASYNC + 7 : case FDDI_FC_LLC_ASYNC + 8 : case FDDI_FC_LLC_ASYNC + 9 : case FDDI_FC_LLC_ASYNC + 10 : case FDDI_FC_LLC_ASYNC + 11 : case FDDI_FC_LLC_ASYNC + 12 : case FDDI_FC_LLC_ASYNC + 13 : case FDDI_FC_LLC_ASYNC + 14 : case FDDI_FC_LLC_ASYNC + 15 : capture_llc(pd, offset, len, ld); return; default : ld->other++; return; } /* fc */ } /* capture_fddi */
static gboolean capture_enc(const guchar *pd, int offset _U_, int len, capture_packet_info_t *cpinfo, const union wtap_pseudo_header *pseudo_header) { guint32 af; if (!BYTES_ARE_IN_FRAME(0, len, BSD_ENC_HDRLEN)) return FALSE; memcpy((char *)&af, (const char *)&pd[0], sizeof(af)); if ((af & 0xFFFF0000) != 0) { /* * BSD AF_ types will always have the upper 16 bits as 0, so if any * of them are non-zero, the af field must be byte-swapped, and * will, at least in DLT_ENC headers, always have at least one of * the lower 16 bits not being 0 (it won't be AF_UNSPEC, which is * 0), so if the af field is byte-swapped, at least one of the * upper 16 bits will be 0. */ af = GUINT32_SWAP_LE_BE(af); } return try_capture_dissector("enc", af, pd, BSD_ENC_HDRLEN, len, cpinfo, pseudo_header); }
void capture_eth(const guchar *pd, int offset, int len, packet_counts *ld) { guint16 etype, length; int ethhdr_type; /* the type of ethernet frame */ if (!BYTES_ARE_IN_FRAME(offset, len, ETH_HEADER_SIZE)) { ld->other++; return; } etype = pntohs(&pd[offset+12]); if (etype <= IEEE_802_3_MAX_LEN) { /* Oh, yuck. Cisco ISL frames require special interpretation of the destination address field; fortunately, they can be recognized by checking the first 5 octets of the destination address, which are 01-00-0C-00-00 or 0C-00-0C-00-00 for ISL frames. */ if ((pd[offset] == 0x01 || pd[offset] == 0x0C) && pd[offset+1] == 0x00 && pd[offset+2] == 0x0C && pd[offset+3] == 0x00 && pd[offset+4] == 0x00) { capture_isl(pd, offset, len, ld); return; } } /* * If the type/length field is <= the maximum 802.3 length, * and is not zero, this is an 802.3 frame, and it's a length * field; it might be an Novell "raw 802.3" frame, with no * 802.2 LLC header, or it might be a frame with an 802.2 LLC * header. * * If the type/length field is >= the minimum Ethernet II length, * this is an Ethernet II frame, and it's a type field. * * If the type/length field is > maximum 802.3 length and < minimum * Ethernet II length, then this is an invalid packet. * * If the type/length field is zero (ETHERTYPE_UNK), this is * a frame used internally by the Cisco MDS switch to contain * Fibre Channel ("Vegas"). We treat that as an Ethernet II * frame; the dissector for those frames registers itself with * an ethernet type of ETHERTYPE_UNK. */ if (etype > IEEE_802_3_MAX_LEN && etype < ETHERNET_II_MIN_LEN) { ld->other++; return; } if (etype <= IEEE_802_3_MAX_LEN && etype != ETHERTYPE_UNK) { length = etype; /* Is there an 802.2 layer? I can tell by looking at the first 2 bytes after the 802.3 header. If they are 0xffff, then what follows the 802.3 header is an IPX payload, meaning no 802.2. (IPX/SPX is they only thing that can be contained inside a straight 802.3 packet). A non-0xffff value means that there's an 802.2 layer inside the 802.3 layer */ if (pd[offset+14] == 0xff && pd[offset+15] == 0xff) { ethhdr_type = ETHERNET_802_3; } else { ethhdr_type = ETHERNET_802_2; } /* Convert the LLC length from the 802.3 header to a total frame length, by adding in the size of any data that preceded the Ethernet header, and adding in the Ethernet header size, and set the payload and captured-payload lengths to the minima of the total length and the frame lengths. */ length += offset + ETH_HEADER_SIZE; if (len > length) len = length; } else { ethhdr_type = ETHERNET_II; } offset += ETH_HEADER_SIZE; switch (ethhdr_type) { case ETHERNET_802_3: capture_ipx(ld); break; case ETHERNET_802_2: capture_llc(pd, offset, len, ld); break; case ETHERNET_II: capture_ethertype(etype, pd, offset, len, ld); break; } }
void capture_radiotap(const guchar *pd, int offset, int len, packet_counts *ld) { guint16 it_len; guint32 present; guint8 rflags; if(!BYTES_ARE_IN_FRAME(offset, len, RADIOTAP_MIN_HEADER_LEN)) { ld->other ++; return; } it_len = pletohs(&pd[RADIOTAP_LENGTH_OFFSET]); if(!BYTES_ARE_IN_FRAME(offset, len, it_len)) { ld->other ++; return; } if(it_len > len) { /* Header length is bigger than total packet length */ ld->other ++; return; } if(it_len < RADIOTAP_MIN_HEADER_LEN) { /* Header length is shorter than fixed-length portion of header */ ld->other ++; return; } present = pletohl(&pd[RADIOTAP_PRESENT_OFFSET]); offset += RADIOTAP_MIN_HEADER_LEN; it_len -= RADIOTAP_MIN_HEADER_LEN; rflags = 0; /* * IEEE80211_RADIOTAP_TSFT is the lowest-order bit. */ if (present & BIT(IEEE80211_RADIOTAP_TSFT)) { if (it_len < 8) { /* No room in header for this field. */ ld->other ++; return; } /* That field is present, and it's 8 bits long. */ offset += 8; it_len -= 8; } /* * IEEE80211_RADIOTAP_FLAGS is the next bit. */ if (present & BIT(IEEE80211_RADIOTAP_FLAGS)) { if (it_len < 1) { /* No room in header for this field. */ ld->other ++; return; } /* That field is present; fetch it. */ if(!BYTES_ARE_IN_FRAME(offset, len, 1)) { ld->other ++; return; } rflags = pd[offset]; } /* 802.11 header follows */ if (rflags & IEEE80211_RADIOTAP_F_DATAPAD) capture_ieee80211_datapad(pd, offset + it_len, len, ld); else capture_ieee80211(pd, offset + it_len, len, ld); }
void capture_arcnet (const guchar *pd, int len, packet_counts *ld, gboolean has_offset, gboolean has_exception) { int offset = has_offset ? 4 : 2; if (!BYTES_ARE_IN_FRAME(offset, len, 1)) { ld->other++; return; } switch (pd[offset]) { case ARCNET_PROTO_IP_1051: /* No fragmentation stuff in the header */ capture_ip(pd, offset + 1, len, ld); break; case ARCNET_PROTO_IP_1201: /* * There's fragmentation stuff in the header. * * XXX - on at least some versions of NetBSD, it appears that we * might we get ARCNET frames, not reassembled packets; we should * perhaps bump "ld->other" for all but the first frame of a packet. * * XXX - but on FreeBSD it appears that we get reassembled packets * on input (but apparently we get frames on output - or maybe * we get the packet *and* all its frames!); how to tell the * difference? It looks from the FreeBSD reassembly code as if * the reassembled packet arrives with the header for the first * frame. It also looks as if, on output, we first get the * full packet, with a header containing none of the fragmentation * stuff, and then get the frames. * * On Linux, we get only reassembled packets, and the exception * frame stuff is hidden - there's a split flag and sequence * number, but it appears that it will never have the exception * frame stuff. * * XXX - what about OpenBSD? And, for that matter, what about * Windows? (I suspect Windows supplies reassembled frames, * as WinPcap, like PF_PACKET sockets, taps into the networking * stack just as other protocols do.) */ offset++; if (!BYTES_ARE_IN_FRAME(offset, len, 1)) { ld->other++; return; } if (has_exception && pd[offset] == 0xff) { /* This is an exception packet. The flag value there is the "this is an exception flag" packet; the next two bytes after it are padding, and another copy of the packet type appears after the padding. */ offset += 4; } capture_ip(pd, offset + 3, len, ld); break; case ARCNET_PROTO_ARP_1051: case ARCNET_PROTO_ARP_1201: /* * XXX - do we have to worry about fragmentation for ARP? */ ld->arp++; break; case ARCNET_PROTO_IPX: ld->ipx++; break; default: ld->other++; break; } }
void capture_llc(const guchar *pd, int offset, int len, packet_counts *ld) { int is_snap; guint16 control; int llc_header_len; if (!BYTES_ARE_IN_FRAME(offset, len, 2)) { ld->other++; return; } is_snap = (pd[offset] == SAP_SNAP) && (pd[offset+1] == SAP_SNAP); llc_header_len = 2; /* DSAP + SSAP */ /* * XXX - the page referred to in the comment above about the * Command/Response bit also implies that LLC Type 2 always * uses extended operation, so we don't need to determine * whether it's basic or extended operation; is that the case? */ control = get_xdlc_control(pd, offset+2, pd[offset+1] & SSAP_CR_BIT); llc_header_len += XDLC_CONTROL_LEN(control, TRUE); if (!BYTES_ARE_IN_FRAME(offset, len, llc_header_len)) { ld->other++; return; } if (!XDLC_IS_INFORMATION(control)) { ld->other++; return; } if (is_snap) capture_snap(pd, offset+llc_header_len, len, ld); else { /* non-SNAP */ switch (pd[offset]) { case SAP_IP: capture_ip(pd, offset + llc_header_len, len, ld); break; case SAP_NETWARE1: case SAP_NETWARE2: capture_ipx(ld); break; case SAP_NETBIOS: capture_netbios(ld); break; case SAP_VINES1: case SAP_VINES2: capture_vines(ld); break; default: ld->other++; break; } } }
void capture_null( const guchar *pd, int len, packet_counts *ld ) { guint32 null_header; /* * BSD drivers that use DLT_NULL - including the FreeBSD 3.2 ISDN-for-BSD * drivers, as well as the 4.4-Lite and FreeBSD loopback drivers - * stuff the AF_ value for the protocol, in *host* byte order, in the * first four bytes. (BSD drivers that use DLT_LOOP, such as recent * OpenBSD loopback drivers, stuff it in *network* byte order in the * first four bytes.) * * However, the IRIX and UNICOS/mp snoop socket mechanism supplies, * on loopback devices, a 4-byte header that has a 2 byte (big-endian) * AF_ value and 2 bytes of 0, so it's * * 0000AAAA * * when read on a little-endian machine and * * AAAA0000 * * when read on a big-endian machine. The current CVS version of libpcap * compensates for this by converting it to standard 4-byte format before * processing the packet, but snoop captures from IRIX or UNICOS/mp * have the 2-byte+2-byte header, as might tcpdump or libpcap captures * with older versions of libpcap. * * AF_ values are small integers, and probably fit in 8 bits (current * values on the BSDs do), and have their upper 24 bits zero. * This means that, in practice, if you look at the header as a 32-bit * integer in host byte order: * * on a little-endian machine: * * a little-endian DLT_NULL header looks like * * 000000AA * * a big-endian DLT_NULL header, or a DLT_LOOP header, looks * like * * AA000000 * * an IRIX or UNICOS/mp DLT_NULL header looks like * * 0000AA00 * * on a big-endian machine: * * a big-endian DLT_NULL header, or a DLT_LOOP header, looks * like * * 000000AA * * a little-endian DLT_NULL header looks like * * AA000000 * * an IRIX or UNICOS/mp DLT_NULL header looks like * * 00AA0000 * * However, according to Gerald Combs, a FreeBSD ISDN PPP dump that * Andreas Klemm sent to wireshark-dev has a packet type of DLT_NULL, * and the family bits look like PPP's protocol field. (Was this an * older, or different, ISDN driver?) Looking at what appears to be * that capture file, it appears that it's using PPP in HDLC framing, * RFC 1549, wherein the first two octets of the frame are 0xFF * (address) and 0x03 (control), so the header bytes are, in order: * * 0xFF * 0x03 * high-order byte of a PPP protocol field * low-order byte of a PPP protocol field * * If we treat that as a 32-bit host-byte-order value, it looks like * * PPPP03FF * * where PPPP is a byte-swapped PPP protocol type if we read it on * a little-endian machine and * * FF03PPPP * * where PPPP is a PPP protocol type if we read it on a big-endian * machine. 0x0000 does not appear to be a valid PPP protocol type * value, so at least one of those hex digits is guaranteed not to * be 0. * * Old versions of libpcap for Linux used DLT_NULL for loopback devices, * but not any other devices. (Current versions use DLT_EN10MB for it.) * The Linux loopback driver puts an *Ethernet* header at the beginning * of loopback packets, with fake source and destination addresses and * the appropriate Ethernet type value; however, those older versions of * libpcap for Linux compensated for this by skipping the source and * destination MAC addresses, replacing them with 2 bytes of 0. * This means that if we're reading the capture on a little-endian * machine, the header, treated as a 32-bit integer, looks like * * EEEE0000 * * where EEEE is a byte-swapped Ethernet type, and if we're reading it * on a big-endian machine, it looks like * * 0000EEEE * * where EEEE is an Ethernet type. * * If the first 2 bytes of the header are FF 03: * * it can't be a big-endian BSD DLT_NULL header, or a DLT_LOOP * header, as AF_ values are small so the first 2 bytes of the * header would be 0; * * it can't be a little-endian BSD DLT_NULL header, as the * resulting AF_ value would be >= 0x03FF, which is too big * for an AF_ value; * * it can't be an IRIX or UNICOS/mp DLT_NULL header, as the * resulting AF_ value with be 0x03FF. * * So the first thing we do is check the first two bytes of the * header; if it's FF 03, we treat the packet as a PPP frame. * * Otherwise, if the upper 16 bits are non-zero, either: * * it's a BSD DLT_NULL or DLT_LOOP header whose AF_ value * is not in our byte order; * * it's an IRIX or UNICOS/mp DLT_NULL header being read on * a big-endian machine; * * it's a Linux DLT_NULL header being read on a little-endian * machine. * * In all those cases except for the IRIX or UNICOS/mp DLT_NULL header, * we should byte-swap it (if it's a Linux DLT_NULL header, that'll * put the Ethernet type in the right byte order). In the case * of the IRIX or UNICOS/mp DLT_NULL header, we should just get * the upper 16 bits as an AF_ value. * * If it's a BSD DLT_NULL or DLT_LOOP header whose AF_ value is not * in our byte order, then the upper 2 hex digits would be non-zero * and the next 2 hex digits down would be zero, as AF_ values fit in * 8 bits, and the upper 2 hex digits are the *lower* 8 bits of the value. * * If it's an IRIX or UNICOS/mp DLT_NULL header, the upper 2 hex digits * would be zero and the next 2 hex digits down would be non-zero, as * the upper 16 bits are a big-endian AF_ value. Furthermore, the * next 2 hex digits down are likely to be < 0x60, as 0x60 is 96, * and, so far, we're far from requiring AF_ values that high. * * If it's a Linux DLT_NULL header, the third hex digit from the top * will be >= 6, as Ethernet types are >= 1536, or 0x0600, and * it's byte-swapped, so the second 2 hex digits from the top are * >= 0x60. * * So, if the upper 16 bits are non-zero: * * if the upper 2 hex digits are 0 and the next 2 hex digits are * in the range 0x00-0x5F, we treat it as a big-endian IRIX or * UNICOS/mp DLT_NULL header; * * otherwise, we byte-swap it and do the next stage. * * If the upper 16 bits are zero, either: * * it's a BSD DLT_NULLor DLT_LOOP header whose AF_ value is in * our byte order; * * it's an IRIX or UNICOS/mp DLT_NULL header being read on * a little-endian machine; * * it's a Linux DLT_NULL header being read on a big-endian * machine. * * In all of those cases except for the IRIX or UNICOS/mp DLT_NULL header, * we should *not* byte-swap it. In the case of the IRIX or UNICOS/mp * DLT_NULL header, we should extract the AF_ value and byte-swap it. * * If it's a BSD DLT_NULL or DLT_LOOP header whose AF_ value is * in our byte order, the upper 6 hex digits would all be zero. * * If it's an IRIX or UNICOS/mp DLT_NULL header, the upper 4 hex * digits would be zero and the next 2 hex digits would not be zero. * Furthermore, the third hex digit from the bottom would be < */ if (!BYTES_ARE_IN_FRAME(0, len, 2)) { ld->other++; return; } if (pd[0] == 0xFF && pd[1] == 0x03) { /* * Hand it to PPP. */ capture_ppp_hdlc(pd, 0, len, ld); } else { /* * Treat it as a normal DLT_NULL header. */ if (!BYTES_ARE_IN_FRAME(0, len, (int)sizeof(null_header))) { ld->other++; return; } memcpy((char *)&null_header, (const char *)&pd[0], sizeof(null_header)); if ((null_header & 0xFFFF0000) != 0) { /* * It is possible that the AF_ type was only a 16 bit value. * IRIX and UNICOS/mp loopback snoop use a 4 byte header with * AF_ type in the first 2 bytes! * BSD AF_ types will always have the upper 8 bits as 0. */ if ((null_header & 0xFF000000) == 0 && (null_header & 0x00FF0000) < 0x00060000) { /* * Looks like a IRIX or UNICOS/mp loopback header, in the * correct byte order. Set the null header value to the * AF_ type, which is in the upper 16 bits of "null_header". */ null_header >>= 16; } else { /* Byte-swap it. */ null_header = GUINT32_SWAP_LE_BE(null_header); } } else {
void capture_tr(const guchar *pd, int offset, int len, packet_counts *ld) { int source_routed = 0; int frame_type; int x; guint8 trn_rif_bytes; guint8 actual_rif_bytes; guint16 first2_sr; /* The trn_hdr struct, as separate variables */ guint8 trn_fc; /* field control field */ const guint8 *trn_shost; /* source host */ if (!BYTES_ARE_IN_FRAME(offset, len, TR_MIN_HEADER_LEN)) { ld->other++; return; } if ((x = check_for_old_linux(pd))) { /* Actually packet starts x bytes into what we have got but with all source routing compressed */ /* pd = &pd[x]; */ offset+=x; } /* get the data */ trn_fc = pd[offset + 1]; trn_shost = &pd[offset + 8]; frame_type = (trn_fc & 192) >> 6; /* if the high bit on the first byte of src hwaddr is 1, then this packet is source-routed */ source_routed = trn_shost[0] & 128; trn_rif_bytes = pd[offset + 14] & 31; if (fix_linux_botches) { /* the Linux 2.0 TR code strips source-route bits in * order to test for SR. This can be removed from most * packets with oltr, but not all. So, I try to figure out * which packets should have been SR here. I'll check to * see if there's a SNAP or IPX field right after * my RIF fields. * * The Linux 2.4.18 code, at least appears to do the * same thing, from a capture I got from somebody running * 2.4.18 (RH 7.1, so perhaps this is a Red Hat * "improvement"). */ if (!source_routed && trn_rif_bytes > 0) { if (pd[offset + 0x0e] != pd[offset + 0x0f]) { first2_sr = pntohs(&pd[offset + 0xe0 + trn_rif_bytes]); if ( (first2_sr == 0xaaaa && pd[offset + 0x10 + trn_rif_bytes] == 0x03) || first2_sr == 0xe0e0 || first2_sr == 0xe0aa ) { source_routed = 1; } } } } if (source_routed) { actual_rif_bytes = trn_rif_bytes; } else { trn_rif_bytes = 0; actual_rif_bytes = 0; } if (fix_linux_botches) { /* this is a silly hack for Linux 2.0.x. Read the comment * below about LLC headers. If we're sniffing our own NIC, * we get a full RIF, sometimes with garbage */ if ((source_routed && trn_rif_bytes == 2 && frame_type == 1) || (!source_routed && frame_type == 1)) { /* look for SNAP or IPX only */ if ( (pd[offset + 0x20] == 0xaa && pd[offset + 0x21] == 0xaa && pd[offset + 0x22] == 03) || (pd[offset + 0x20] == 0xe0 && pd[offset + 0x21] == 0xe0) ) { actual_rif_bytes = 18; } else if ( pd[offset + 0x23] == 0 && pd[offset + 0x24] == 0 && pd[offset + 0x25] == 0 && pd[offset + 0x26] == 0x00 && pd[offset + 0x27] == 0x11) { actual_rif_bytes = 18; /* Linux 2.0.x also requires drivers pass up * a fake SNAP and LLC header before the * real LLC hdr for all Token Ring frames * that arrive with DSAP and SSAP != 0xAA * (i.e. for non SNAP frames e.g. for Netware * frames) the fake SNAP header has the * ETH_P_TR_802_2 ether type (0x0011) and the protocol id * bytes as zero frame looks like :- * TR Header | Fake LLC | Fake SNAP | Wire LLC | Rest of data */ offset += 8; /* Skip fake LLC and SNAP */ } } } offset += actual_rif_bytes + TR_MIN_HEADER_LEN; /* The package is either MAC or LLC */ switch (frame_type) { /* MAC */ case 0: ld->other++; break; case 1: capture_llc(pd, offset, len, ld); break; default: /* non-MAC, non-LLC, i.e., "Reserved" */ ld->other++; break; } }