📄 decode.c
字号:
/* $Id: decode.c,v 1.26 2001/01/26 16:40:44 roesch Exp $ *//*** Copyright (C) 1998,1999,2000,2001 Martin Roesch <roesch@clark.net>**** This program is free software; you can redistribute it and/or modify** it under the terms of the GNU General Public License as published by** the Free Software Foundation; either version 2 of the License, or** (at your option) any later version.**** This program is distributed in the hope that it will be useful,** but WITHOUT ANY WARRANTY; without even the implied warranty of** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the** GNU General Public License for more details.**** You should have received a copy of the GNU General Public License** along with this program; if not, write to the Free Software** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.*/#include "decode.h"/* * Function: DecodeEthPkt(Packet *, char *, struct pcap_pkthdr*, u_int8_t*) * * Purpose: Decode those fun loving ethernet packets, one at a time! * * Arguments: p => pointer to the decoded packet struct * user => Utility pointer (unused) * pkthdr => ptr to the packet header * pkt => pointer to the real live packet data * * Returns: void function */void DecodeEthPkt(Packet * p, struct pcap_pkthdr * pkthdr, u_int8_t * pkt){ u_int32_t pkt_len; /* suprisingly, the length of the packet */ u_int32_t cap_len; /* caplen value */ bzero((char *) p, sizeof(Packet)); p->pkth = pkthdr; p->pkt = pkt; /* set the lengths we need */ pkt_len = pkthdr->len; /* total packet length */ cap_len = pkthdr->caplen; /* captured packet length */ if(snaplen < pkt_len) pkt_len = cap_len;#ifdef DEBUG printf("Packet!\n"); printf("caplen: %lu pktlen: %lu\n", (unsigned long)cap_len, (unsigned long)pkt_len);#endif /* do a little validation */ if(p->pkth->caplen < ETHERNET_HEADER_LEN) { if(pv.verbose_flag) { ErrorMessage("Captured data length < Ethernet header length! (%d bytes)\n", p->pkth->caplen); } return; } /* lay the ethernet structure over the packet data */ p->eh = (EtherHdr *) pkt;#ifdef DEBUG ErrorMessage("%X %X\n", *p->eh->ether_src, *p->eh->ether_dst);#endif /* grab out the network type */ switch(ntohs(p->eh->ether_type)) { case ETHERNET_TYPE_IP:#ifdef DEBUG printf("IP datagram size calculated to be %lu bytes\n",(unsigned long)(cap_len - ETHERNET_HEADER_LEN));#endif DecodeIP(p->pkt + ETHERNET_HEADER_LEN, cap_len - ETHERNET_HEADER_LEN, p); /* DecodeIP(p->pkt+ETHERNET_HEADER_LEN, cap_len, p); */ return; case ETHERNET_TYPE_ARP: case ETHERNET_TYPE_REVARP: pc.arp++; if(pv.showarp_flag) { DecodeARP(p->pkt + ETHERNET_HEADER_LEN, cap_len - ETHERNET_HEADER_LEN, p); } return; case ETHERNET_TYPE_IPV6: pc.ipv6++; if(pv.showipv6_flag) DecodeIPV6(p->pkt + ETHERNET_HEADER_LEN, (cap_len - ETHERNET_HEADER_LEN)); return; case ETHERNET_TYPE_IPX: pc.ipx++; if(pv.showipx_flag) DecodeIPX(p->pkt + ETHERNET_HEADER_LEN, (cap_len - ETHERNET_HEADER_LEN)); return; default: pc.other++; return; } return;}/* * Function: DecodeNullPkt(Packet *, char *, struct pcap_pkthdr*, u_int8_t*) * * Purpose: Decoding on loopback devices. * * Arguments: p => pointer to decoded packet struct * user => Utility pointer, unused * pkthdr => ptr to the packet header * pkt => pointer to the real live packet data * * Returns: void function */void DecodeNullPkt(Packet * p, struct pcap_pkthdr * pkthdr, u_int8_t * pkt){ u_int32_t len; u_int32_t cap_len; bzero((char *) p, sizeof(Packet)); p->pkth = pkthdr; p->pkt = pkt; len = pkthdr->len; cap_len = pkthdr->caplen;#ifdef DEBUG printf("Packet!\n");#endif /* do a little validation */ if(cap_len < NULL_HDRLEN) { if(pv.verbose_flag) { ErrorMessage("NULL header length < captured len! (%d bytes)\n", cap_len); } return; } DecodeIP(p->pkt + NULL_HDRLEN, cap_len - NULL_HDRLEN, p);}/* * Function: DecodeTRPkt(Packet *, char *, struct pcap_pkthdr*, u_int8_t*) * * Purpose: Decode Token Ring packets! * * Arguments: p=> pointer to decoded packet struct * user => Utility pointer, unused * pkthdr => ptr to the packet header * pkt => pointer to the real live packet data * * Returns: void function */void DecodeTRPkt(Packet * p, struct pcap_pkthdr * pkthdr, u_int8_t * pkt){ u_int32_t pkt_len; /* suprisingly, the length of the packet */ u_int32_t cap_len; /* caplen value */ u_int32_t dataoff; /* data offset is variable here */ bzero((char *) p, sizeof(Packet)); p->pkth = pkthdr; p->pkt = pkt; /* set the lengths we need */ pkt_len = pkthdr->len; /* total packet length */ cap_len = pkthdr->caplen; /* captured packet length */ if(snaplen < pkt_len) pkt_len = cap_len;#ifdef DEBUG printf("Packet!\n"); printf("caplen: %lu pktlen: %lu\n",(unsigned long)cap_len,(unsigned long) pkt_len);#endif /* do a little validation */ if(p->pkth->caplen < TR_HLEN) { if(pv.verbose_flag) ErrorMessage("Captured data length < Token Ring header length! (%d < %d bytes)\n", p->pkth->caplen, TR_HLEN); return; } /* lay the tokenring header structure over the packet data */ p->trh = (Trh_hdr *) pkt;/* * according to rfc 1042: The presence of a Routing Information Field is indicated by the Most Significant Bit (MSB) of the source address, called the Routing Information Indicator (RII). If the RII equals zero, a RIF is not present. If the RII equals 1, the RIF is present. .. However the MSB is already zeroed by this moment, so there's no real way to figure out whether RIF is presented in packet, so we are doing some tricks to find IPARP signature..*/ /* * first I assume that we have single-ring network with no RIF * information presented in frame */ p->trhllc = (Trh_llc *) (pkt + sizeof(Trh_hdr)); if(p->trhllc->dsap != IPARP_SAP && p->trhllc->ssap != IPARP_SAP) { /* * DSAP != SSAP != 0xAA .. either we are having frame which doesn't * carry IP datagrams or has RIF information present. We assume * lattest ... */ p->trhmr = (Trh_mr *) (pkt + sizeof(Trh_hdr)); p->trhllc = (Trh_llc *) (pkt + sizeof(Trh_hdr) + p->trhmr->len); dataoff = sizeof(Trh_hdr) + p->trhmr->len + sizeof(Trh_llc); } else { p->trhllc = (Trh_llc *) (pkt + sizeof(Trh_hdr)); dataoff = sizeof(Trh_hdr) + sizeof(Trh_llc); } /* * ideally we would need to check both SSAP, DSAP, and protoid fields: IP * datagrams and ARP requests and replies are transmitted in standard * 802.2 LLC Type 1 Unnumbered Information format, control code 3, with * the DSAP and the SSAP fields of the 802.2 header set to 170, the * assigned global SAP value for SNAP [6]. The 24-bit Organization Code * in the SNAP is zero, and the remaining 16 bits are the EtherType from * Assigned Numbers [7] (IP = 2048, ARP = 2054). .. but we would check * SSAP and DSAP and assume this would be enough to trust. */ if(p->trhllc->dsap != IPARP_SAP && p->trhllc->ssap != IPARP_SAP) {#ifdef DEBUG ErrorMessage("DSAP and SSAP arent set to SNAP\n");#endif p->trhllc = NULL; return; } pkt_len -= dataoff; cap_len -= dataoff; switch(htons(p->trhllc->ethertype)) { case ETHERNET_TYPE_IP:#ifdef DEBUG printf("Decoding IP\n");#endif DecodeIP(p->pkt + dataoff, cap_len, p); return; case ETHERNET_TYPE_ARP: case ETHERNET_TYPE_REVARP:#ifdef DEBUG printf("Decoding ARP\n");#endif pc.arp++; return; default:#ifdef DEBUG printf("Unknown network protocol: %d\n", htons(p->trhllc->ethertype));#endif pc.other++; return; } return;}/* * Function: DecodeFDDIPkt(Packet *, char *, struct pcap_pkthdr*, u_int8_t*) * * Purpose: Mainly taken from CyberPsycotic's Token Ring Code -worm5er * * Arguments: p => pointer to decoded packet struct * user => Utility pointer, unused * pkthdr => ptr to the packet header * pkt => pointer to the real live packet data * * Returns: void function */void DecodeFDDIPkt(Packet * p, struct pcap_pkthdr * pkthdr, u_int8_t * pkt){ u_int32_t pkt_len; /* length of the packet */ u_int32_t cap_len; /* capture length variable */ u_int32_t dataoff; /* data offset is variable here */ bzero((char *) p, sizeof(Packet)); p->pkth = pkthdr; p->pkt = pkt; pkt_len = pkthdr->len; cap_len = pkthdr->caplen; if(snaplen < pkt_len) { pkt_len = cap_len; }#ifdef DEBUG printf("Packet!\n"); printf("caplen: %lu pktlen: %lu\n",(unsigned long) cap_len,(unsigned long) pkt_len);#endif /* Bounds checking (might not be right yet -worm5er) */ if(p->pkth->caplen < FDDI_MIN_HLEN) { if(pv.verbose_flag) { ErrorMessage("Captured data length < FDDI header length! " "(%d %d bytes)\n", p->pkth->caplen, FDDI_MIN_HLEN); return; } } /* let's put this in as the fddi header structure */ p->fddihdr = (Fddi_hdr *) pkt; p->fddisaps = (Fddi_llc_saps *) (pkt + sizeof(Fddi_hdr)); /* First we'll check and see if it's an IP/ARP Packet... */ /* Then we check to see if it's a SNA packet */ /* * Lastly we'll declare it none of the above and just slap something * generic on it to discard it with (I know that sucks, but heck we're * only looking for IP/ARP type packets currently... -worm5er */ if((p->fddisaps->dsap == FDDI_DSAP_IP) && (p->fddisaps->ssap == FDDI_SSAP_IP)) { p->fddiiparp = (Fddi_llc_iparp *) (pkt + sizeof(Fddi_hdr) + sizeof(Fddi_llc_saps)); dataoff = sizeof(Fddi_hdr) + sizeof(Fddi_llc_saps) + sizeof(Fddi_llc_iparp); } else if((p->fddisaps->dsap == FDDI_DSAP_SNA) && (p->fddisaps->ssap == FDDI_SSAP_SNA)) { p->fddisna = (Fddi_llc_sna *) (pkt + sizeof(Fddi_hdr) + sizeof(Fddi_llc_saps)); dataoff = sizeof(Fddi_hdr) + sizeof(Fddi_llc_saps) + sizeof(Fddi_llc_sna); } else { p->fddiother = (Fddi_llc_other *) (pkt + sizeof(Fddi_hdr) + sizeof(Fddi_llc_other)); dataoff = sizeof(Fddi_hdr) + sizeof(Fddi_llc_saps) + sizeof(Fddi_llc_other); } /* * Now let's see if we actually care about the packet... If we don't, * throw it out!!! */ if((p->fddisaps->dsap != FDDI_DSAP_IP) && (p->fddisaps->ssap != FDDI_SSAP_IP)) {#ifdef DEBUG ErrorMessage("This FDDI Packet isn't an IP/ARP packet...\n");#endif return; } pkt_len -= dataoff; cap_len -= dataoff; switch(htons(p->fddiiparp->ethertype)) { case ETHERNET_TYPE_IP:#ifdef DEBUG printf("Decoding IP\n");#endif DecodeIP(p->pkt + dataoff, cap_len, p); return; case ETHERNET_TYPE_ARP: case ETHERNET_TYPE_REVARP:#ifdef DEBUG printf("Decoding ARP\n");#endif pc.arp++; return; default:#ifdef DEBUG printf("Unknown network protocol: %d\n", htons(p->fddiiparp->ethertype));#endif pc.other++; return; } return;}/* * Function: DecodePppPkt(Packet *, char *, struct pcap_pkthdr*, u_int8_t*) * * Purpose: Decoded PPP traffic * * Arguments: p => pointer to decoded packet struct * user => Utility pointer, unused * pkthdr => ptr to the packet header * pkt => pointer to the real live packet data * * Returns: void function */void DecodePppPkt(Packet * p, struct pcap_pkthdr * pkthdr, u_int8_t * pkt){ static int had_vj = 0; u_int32_t len; u_int32_t cap_len; struct ppp_header *ppphdr; bzero((char *) p, sizeof(Packet)); p->pkth = pkthdr; p->pkt = pkt; ppphdr = (struct ppp_header *)pkt; len = pkthdr->len; cap_len = pkthdr->caplen;#ifdef DEBUG printf("Packet!\n");#endif /* do a little validation */ if(cap_len < PPP_HDRLEN) { ErrorMessage("PPP header length < captured len! (%d bytes)\n", cap_len); return; } /* * We only handle uncompressed packets. Handling VJ compression would mean * to implement a PPP state machine. */ switch (ntohs(ppphdr->protocol)) { case PPP_VJ_COMP: if (!had_vj) ErrorMessage("PPP link seems to use VJ compression, cannot handle compressed packets!\n"); had_vj = 1; break; case PPP_VJ_UCOMP: /* VJ compression modifies the protocol field. It must be set * to tcp (only TCP packets can be VJ compressed) */ if(cap_len < PPP_HDRLEN + IP_HEADER_LEN) { ErrorMessage("PPP VJ min packet length > captured len! (%d bytes)\n", cap_len); return; } ((IPHdr *)(p->pkt + PPP_HDRLEN))->ip_proto = IPPROTO_TCP; /* fall through */ case PPP_IP: DecodeIP(p->pkt + PPP_HDRLEN, cap_len - PPP_HDRLEN, p); break; case PPP_IPX: DecodeIPX(p->pkt + PPP_HDRLEN, cap_len - PPP_HDRLEN); break; }}/* * Function: DecodeSlipPkt(Packet *, char *, struct pcap_pkthdr*, u_int8_t*) * * Purpose: Decode SLIP traffic * * Arguments: p => pointer to decoded packet struct * user => Utility pointer, unused * pkthdr => ptr to the packet header * pkt => pointer to the real live packet data * * Returns: void function */void DecodeSlipPkt(Packet * p, struct pcap_pkthdr * pkthdr, u_int8_t * pkt){ u_int32_t len; u_int32_t cap_len; bzero((char *) p, sizeof(Packet)); p->pkth = pkthdr; p->pkt = pkt; len = pkthdr->len; cap_len = pkthdr->caplen;#ifdef DEBUG printf("Packet!\n");#endif /* do a little validation */ if(cap_len < SLIP_HEADER_LEN)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -