void capture_ipfc (const guchar *pd, int len, packet_counts *ld) { if (!BYTES_ARE_IN_FRAME(0, len, 16)) { ld->other++; return; } capture_llc(pd, 16, len, ld); }
void capture_sll(const guchar *pd, int len, packet_counts *ld) { guint16 protocol; if (!BYTES_ARE_IN_FRAME(0, len, SLL_HEADER_SIZE)) { ld->other++; return; } protocol = pntohs(&pd[14]); if (protocol <= 1536) { /* yes, 1536 - that's how Linux does it */ /* * "proto" is *not* a length field, it's a Linux internal * protocol type. */ switch (protocol) { case LINUX_SLL_P_802_2: /* * 802.2 LLC. */ capture_llc(pd, len, SLL_HEADER_SIZE, ld); break; case LINUX_SLL_P_ETHERNET: /* * Ethernet. */ capture_eth(pd, SLL_HEADER_SIZE, len, ld); break; case LINUX_SLL_P_802_3: /* * Novell IPX inside 802.3 with no 802.2 LLC * header. */ capture_ipx(ld); break; case LINUX_SLL_P_PPPHDLC: /* * PPP HDLC. */ capture_ppp_hdlc(pd, len, SLL_HEADER_SIZE, ld); break; default: ld->other++; break; } } else capture_ethertype(protocol, pd, SLL_HEADER_SIZE, 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 */
void capture_ethertype(guint16 etype, const guchar *pd, int offset, int len, packet_counts *ld) { switch (etype) { case ETHERTYPE_ARP: ld->arp++; break; case ETHERTYPE_IP: capture_ip(pd, offset, len, ld); break; case ETHERTYPE_IPv6: capture_ipv6(pd, offset, len, ld); break; case ETHERTYPE_IPX: capture_ipx(ld); break; case ETHERTYPE_VLAN: capture_vlan(pd, offset, len, ld); break; case ETHERTYPE_IEEE_802_1AD: case ETHERTYPE_IEEE_802_1AH: capture_ieee8021ah(pd, offset, len, ld); break; case ETHERTYPE_VINES_IP: case ETHERTYPE_VINES_ECHO: capture_vines(ld); break; case ETHERTYPE_BPQ: capture_bpq(pd, offset, len, ld); break; case ETHERTYPE_JUMBO_LLC: capture_llc(pd, offset, len, ld); break; default: ld->other++; break; } }
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_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; } }