?? op_decode.c
字號:
/* $Id: op_decode.c,v 1.9 2004/04/03 19:57:32 andrewbaker Exp $ *//*** Copyright (C) 1998-2001 Martin Roesch <roesch@sourcefire.com>** Portions Copyright (C) 2002 Andrew R. Baker <andrewb@snort.org>**** This program is distributed under the terms of version 1.0 of the ** Q Public License. See LICENSE.QPL for further details.**** 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.***/#include "config.h"#include <string.h>#ifdef SOLARIS#include <strings.h>#endif#include "util.h"#include "op_decode.h"#include "barnyard.h"#include "input-plugins/dp_log.h"int DecodePacket(Packet *p, SnortPktHeader *pkthdr, uint8_t *pkt){ switch(linktype) { case 0: /* Null linktype */ DecodeIP(pkt, pkthdr->caplen, p); return 0; case 1: /* Ethernet */ DecodeEthPkt(p, pkthdr, pkt); return 0; } return -1;}/* * Function: DecodeEthPkt(Packet *, SnortPktHeader *, u_int8_t*) * * Purpose: Decode those fun loving ethernet packets, one at a time! * * Arguments: p => pointer to the decoded packet struct * pkthdr => ptr to the packet header * pkt => pointer to the real live packet data * * Returns: void function */void DecodeEthPkt(Packet *p, SnortPktHeader *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; /* set the lengths we need */ pkt_len = pkthdr->pktlen; /* total packet length */ cap_len = pkthdr->caplen; /* captured packet length */ /* do a little validation */ if(pkthdr->caplen < ETHERNET_HEADER_LEN) { if(pv.verbose >= 3) LogMessage("Captured data length < Ethernet header " "length! (%d bytes)\n", cap_len); return; } /* lay the ethernet structure over the packet data */ p->eh = (EtherHdr *) pkt; /* grab out the network type */ switch(ntohs(p->eh->ether_type)) { case ETHERNET_TYPE_PPPoE_DISC: case ETHERNET_TYPE_PPPoE_SESS: DecodePPPoEPkt(p, pkthdr, pkt); return; case ETHERNET_TYPE_IP: DecodeIP(pkt + ETHERNET_HEADER_LEN, cap_len - ETHERNET_HEADER_LEN, p); return; case ETHERNET_TYPE_ARP: case ETHERNET_TYPE_REVARP: DecodeARP(pkt + ETHERNET_HEADER_LEN, cap_len - ETHERNET_HEADER_LEN, p); return; case ETHERNET_TYPE_IPV6: DecodeIPV6(pkt + ETHERNET_HEADER_LEN, (cap_len - ETHERNET_HEADER_LEN)); return; case ETHERNET_TYPE_IPX: DecodeIPX(pkt + ETHERNET_HEADER_LEN, (cap_len - ETHERNET_HEADER_LEN)); return; case ETHERNET_TYPE_8021Q: DecodeVlan(pkt + ETHERNET_HEADER_LEN, cap_len - ETHERNET_HEADER_LEN, p); return; default: if(pv.verbose >= 3) LogMessage("Unknown Network header (0x%X)...\n", p->eh->ether_type); return; } return;}void DecodeVlan(u_int8_t * pkt, const u_int32_t len, Packet * p){ u_int16_t pri; p->vh = (VlanTagHdr *) pkt; pri = (0xe000 & ntohs(p->vh->vth_vlan))>>13; /* check to see if we've got an encapsulated LLC layer */ if(pri != 0) { p->ehllc = (EthLlc *) (pkt + sizeof(VlanTagHdr)); if(p->ehllc->dsap == ETH_DSAP_IP && p->ehllc->ssap == ETH_SSAP_IP) { p->ehllcother = (EthLlcOther *) (pkt + sizeof(VlanTagHdr) + sizeof(EthLlc)); switch(ntohs(p->ehllcother->proto_id)) { case ETHERNET_TYPE_IP: DecodeIP(pkt + sizeof(VlanTagHdr) + sizeof(EthLlc) + sizeof(EthLlcOther), len - sizeof(VlanTagHdr), p); return; case ETHERNET_TYPE_ARP: case ETHERNET_TYPE_REVARP: DecodeARP(pkt + sizeof(VlanTagHdr)+ sizeof(EthLlc) + sizeof(EthLlcOther), len - sizeof(VlanTagHdr), p); return; default: return; } } } else { switch(ntohs(p->vh->vth_proto)) { case ETHERNET_TYPE_IP: DecodeIP(pkt + sizeof(VlanTagHdr), len - sizeof(VlanTagHdr), p); return; case ETHERNET_TYPE_ARP: case ETHERNET_TYPE_REVARP: DecodeARP(pkt + sizeof(VlanTagHdr), len - sizeof(VlanTagHdr), p); return; default: 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, SnortPktHeader * 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; ppphdr = (struct ppp_header *)pkt; len = pkthdr->pktlen; cap_len = pkthdr->caplen; /* do a little validation */ if(cap_len < PPP_HDRLEN) { if(pv.verbose >= 3) LogMessage("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) LogMessage("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) { if(pv.verbose >= 3) LogMessage("PPP VJ min packet length > captured len! " "(%d bytes)\n", cap_len); return; } ((IPHdr *)(pkt + PPP_HDRLEN))->ip_proto = IPPROTO_TCP; /* fall through */ case PPP_IP: DecodeIP(pkt + PPP_HDRLEN, cap_len - PPP_HDRLEN, p); break; case PPP_IPX: DecodeIPX(pkt + PPP_HDRLEN, cap_len - PPP_HDRLEN); break; }}/* * Function: DecodePPPoEPkt(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 * * see http://www.faqs.org/rfcs/rfc2516.html * */void DecodePPPoEPkt(Packet *p, SnortPktHeader *pkthdr, u_int8_t *pkt){ u_int32_t pkt_len; /* suprisingly, the length of the packet */ u_int32_t cap_len; /* caplen value */ PPPoEHdr *ppppoep=0; PPPoE_Tag *ppppoe_tag=0; PPPoE_Tag tag; /* needed to avoid alignment problems */ bzero((char *) p, sizeof(Packet)); /* set the lengths we need */ pkt_len = pkthdr->pktlen; /* total packet length */ cap_len = pkthdr->caplen; /* captured packet length */ /* do a little validation */ if(pkthdr->caplen < ETHERNET_HEADER_LEN) { if(pv.verbose >= 3) LogMessage("Captured data length < Ethernet header length! " "(%d bytes)\n", cap_len); return; } /* lay the ethernet structure over the packet data */ p->eh = (EtherHdr *) pkt; ppppoep = (PPPoEHdr *)pkt; /* grab out the network type */ switch(ntohs(p->eh->ether_type)) { case ETHERNET_TYPE_PPPoE_DISC: case ETHERNET_TYPE_PPPoE_SESS: break; default: return; } if (ntohs(p->eh->ether_type) != ETHERNET_TYPE_PPPoE_DISC) { DecodePppPkt(p, pkthdr, pkt+18); return; } ppppoe_tag = (PPPoE_Tag *)(pkt + sizeof(PPPoEHdr)); while (ppppoe_tag < (PPPoE_Tag *)(pkt + pkthdr->caplen)) { /* no guarantee in PPPoE spec that ppppoe_tag is aligned at all... */ memcpy(&tag, ppppoe_tag, sizeof(tag)); if (ntohs(tag.length) > 0) { } ppppoe_tag = (PPPoE_Tag *)((char *)(ppppoe_tag+1)+ntohs(tag.length)); } return;}/* * Function: DecodeIP(u_int8_t *, const u_int32_t, Packet *) * * Purpose: Decode the IP network layer * * Arguments: pkt => ptr to the packet data * len => length from here to the end of the packet * p => pointer to the packet decode struct * * Returns: void function */void DecodeIP(u_int8_t * pkt, const u_int32_t len, Packet * p){ u_int32_t ip_len; /* length from the start of the ip hdr to the * pkt end */ u_int32_t hlen; /* ip header length */ /* lay the IP struct over the raw data */ p->iph = (IPHdr *) pkt; /* do a little validation */ if(len < IP_HEADER_LEN) { if(pv.verbose >= 3) LogMessage("IP header truncated! (%d bytes)\n", len); p->iph = NULL; return; } /* * with datalink DLT_RAW it's impossible to differ ARP datagrams from IP. * So we are just ignoring non IP datagrams */ if(IP_VER(p->iph) != 4) { if(pv.verbose >= 3) LogMessage("[!] WARNING: Not IPv4 datagram! " "([ver: 0x%x][len: 0x%x])\n", IP_VER(p->iph), p->iph->ip_len); p->iph = NULL; return; } /* set the IP datagram length */ ip_len = ntohs(p->iph->ip_len); /* set the IP header length */ hlen = IP_HLEN(p->iph) << 2; if (ip_len != len) { if (ip_len > len) { ip_len = len; } } if(ip_len < hlen) { if(pv.verbose >= 3) LogMessage("[!] WARNING: IP dgm len (%d bytes) < IP hdr len " "(%d bytes), packet discarded\n", ip_len, hlen); return; } /* test for IP options */ p->ip_options_len = hlen - IP_HEADER_LEN; if(p->ip_options_len > 0) { p->ip_options_data = pkt + IP_HEADER_LEN; DecodeIPOptions((pkt + IP_HEADER_LEN), p->ip_options_len, p); } else { p->ip_option_count = 0; } /* set the remaining packet length */ ip_len -= hlen; /* check for fragmented packets */ p->frag_offset = ntohs(p->iph->ip_off); /* * get the values of the reserved, more * fragments and don't fragment flags */ if(((p->frag_offset & 0x8000) >> 15)) p->pkt_flags |= PKT_RB_FLAG; if(((p->frag_offset & 0x4000) >> 14)) p->pkt_flags |= PKT_DF_FLAG; if(((p->frag_offset & 0x2000) >> 13)) p->pkt_flags |= PKT_MF_FLAG; /* mask off the high bits in the fragment offset field */ p->frag_offset &= 0x1FFF; if(p->frag_offset || (p->pkt_flags & PKT_MF_FLAG)) { /* set the packet fragment flag */ p->pkt_flags |= PKT_FRAG_FLAG; } /* if this packet isn't a fragment */ if((p->pkt_flags & PKT_FRAG_FLAG) == 0) { switch(p->iph->ip_proto) { case IPPROTO_TCP: DecodeTCP(pkt + hlen, ip_len, p); return; case IPPROTO_UDP: DecodeUDP(pkt + hlen, ip_len, p); return; case IPPROTO_ICMP: DecodeICMP(pkt + hlen, ip_len, p); return; default: p->data = pkt + hlen; p->dsize = ip_len; return; } } else { /* set the payload pointer and payload size */ p->data = pkt + hlen; p->dsize = ip_len; }}/* * Function: DecodeIPOnly(u_int8_t *, const u_int32_t, Packet *) * * Purpose: Decode the IP network layer but not recurse * * Arguments: pkt => ptr to the packet data * len => length from here to the end of the packet * p => pointer to dummy packet decode struct * * Returns: void function */int DecodeIPOnly(u_int8_t * pkt, const u_int32_t len, Packet * p){ u_int32_t ip_len; /* * length from the start of the ip hdr to the * pkt end */ u_int32_t hlen; /* ip header length */ /* lay the IP struct over the raw data */ p->iph = (IPHdr *) pkt; /* do a little validation */ if(len < IP_HEADER_LEN) { if(pv.verbose >= 3) LogMessage("ICMP Unreachable IP short header (%d bytes)\n", len); p->iph = NULL; return(0); } /* * with datalink DLT_RAW it's impossible to differ ARP datagrams from IP. * So we are just ignoring non IP datagrams */ if(IP_VER(p->iph) != 4) { if(pv.verbose >= 3) LogMessage("[!] WARNING: ICMP Unreachable not IPv4 datagram " "([ver: 0x%x][len: 0x%x])\n", IP_VER(p->iph), p->iph->ip_len); p->iph = NULL; return(0); } /* set the IP datagram length */ ip_len = ntohs(p->iph->ip_len);
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -