From: Josh Date: Wed, 16 Apr 2014 16:02:53 +0000 (-0400) Subject: deleteing old protocols directory X-Git-Tag: 3.0.0-233~1559^2~27 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=ebcc9ba93b4ac9e10791ddd45dd269b1999e2c4e;p=thirdparty%2Fsnort3.git deleteing old protocols directory --- diff --git a/src/protocols/checksum.h b/src/protocols/checksum.h deleted file mode 100644 index 7e883d69e..000000000 --- a/src/protocols/checksum.h +++ /dev/null @@ -1,603 +0,0 @@ -/* -** Copyright (C) 2000,2001 Christopher Cramer -** Snort is Copyright (C) 1998-2002 Martin Roesch -** -** Copyright (C) 2014 Cisco and/or its affiliates. All rights reserved. -** Copyright (C) 2002-2013 Sourcefire, Inc. -** Marc Norton -** -** This program is free software; you can redistribute it and/or modify -** it under the terms of the GNU General Public License Version 2 as -** published by the Free Software Foundation. You may not use, modify or -** distribute this program under any other version of the GNU General -** Public License. -** -** 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -** -** -** 7/2002 Marc Norton - added inline/optimized checksum routines -** these handle all hi/low endian issues -** 8/2002 Marc Norton - removed old checksum code and prototype -** -*/ - -#ifndef CHECKSUM_H -#define CHECKSUM_H - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include "snort_debug.h" -#include - -typedef struct -{ - uint32_t sip[4], dip[4]; - uint8_t zero; - uint8_t protocol; - uint16_t len; -} pseudoheader6; - -typedef struct -{ - uint32_t sip, dip; - uint8_t zero; - uint8_t protocol; - uint16_t len; -} pseudoheader; - -/* -* checksum IP - header=20+ bytes -* -* w - short words of data -* blen - byte length -* -*/ -static inline unsigned short in_chksum_ip( unsigned short * w, int blen ) -{ - unsigned int cksum; - - /* IP must be >= 20 bytes */ - cksum = w[0]; - cksum += w[1]; - cksum += w[2]; - cksum += w[3]; - cksum += w[4]; - cksum += w[5]; - cksum += w[6]; - cksum += w[7]; - cksum += w[8]; - cksum += w[9]; - - blen -= 20; - w += 10; - - while( blen ) /* IP-hdr must be an integral number of 4 byte words */ - { - cksum += w[0]; - cksum += w[1]; - w += 2; - blen -= 4; - } - - cksum = (cksum >> 16) + (cksum & 0x0000ffff); - cksum += (cksum >> 16); - - return (unsigned short) (~cksum); -} - -/* -* checksum tcp -* -* h - pseudo header - 12 bytes -* d - tcp hdr + payload -* dlen - length of tcp hdr + payload in bytes -* -*/ -static inline unsigned short in_chksum_tcp(pseudoheader *ph, - unsigned short * d, int dlen ) -{ - uint16_t *h = (uint16_t *)ph; - unsigned int cksum; - unsigned short answer=0; - - /* PseudoHeader must have 12 bytes */ - cksum = h[0]; - cksum += h[1]; - cksum += h[2]; - cksum += h[3]; - cksum += h[4]; - cksum += h[5]; - - /* TCP hdr must have 20 hdr bytes */ - cksum += d[0]; - cksum += d[1]; - cksum += d[2]; - cksum += d[3]; - cksum += d[4]; - cksum += d[5]; - cksum += d[6]; - cksum += d[7]; - cksum += d[8]; - cksum += d[9]; - - dlen -= 20; /* bytes */ - d += 10; /* short's */ - - while(dlen >=32) - { - cksum += d[0]; - cksum += d[1]; - cksum += d[2]; - cksum += d[3]; - cksum += d[4]; - cksum += d[5]; - cksum += d[6]; - cksum += d[7]; - cksum += d[8]; - cksum += d[9]; - cksum += d[10]; - cksum += d[11]; - cksum += d[12]; - cksum += d[13]; - cksum += d[14]; - cksum += d[15]; - d += 16; - dlen -= 32; - } - - while(dlen >=8) - { - cksum += d[0]; - cksum += d[1]; - cksum += d[2]; - cksum += d[3]; - d += 4; - dlen -= 8; - } - - while(dlen > 1) - { - cksum += *d++; - dlen -= 2; - } - - if( dlen == 1 ) - { - /* printf("new checksum odd byte-packet\n"); */ - *(unsigned char*)(&answer) = (*(unsigned char*)d); - - /* cksum += (uint16_t) (*(uint8_t*)d); */ - - cksum += answer; - } - - cksum = (cksum >> 16) + (cksum & 0x0000ffff); - cksum += (cksum >> 16); - - return (unsigned short)(~cksum); -} -/* -* checksum tcp for IPv6. -* -* h - pseudo header - 12 bytes -* d - tcp hdr + payload -* dlen - length of tcp hdr + payload in bytes -* -*/ -static inline unsigned short in_chksum_tcp6(pseudoheader6 *ph, - unsigned short * d, int dlen ) -{ - uint16_t *h = (uint16_t *)ph; - unsigned int cksum; - unsigned short answer=0; - - /* PseudoHeader must have 36 bytes */ - cksum = h[0]; - cksum += h[1]; - cksum += h[2]; - cksum += h[3]; - cksum += h[4]; - cksum += h[5]; - cksum += h[6]; - cksum += h[7]; - cksum += h[8]; - cksum += h[9]; - cksum += h[10]; - cksum += h[11]; - cksum += h[12]; - cksum += h[13]; - cksum += h[14]; - cksum += h[15]; - cksum += h[16]; - cksum += h[17]; - - /* TCP hdr must have 20 hdr bytes */ - cksum += d[0]; - cksum += d[1]; - cksum += d[2]; - cksum += d[3]; - cksum += d[4]; - cksum += d[5]; - cksum += d[6]; - cksum += d[7]; - cksum += d[8]; - cksum += d[9]; - - dlen -= 20; /* bytes */ - d += 10; /* short's */ - - while(dlen >=32) - { - cksum += d[0]; - cksum += d[1]; - cksum += d[2]; - cksum += d[3]; - cksum += d[4]; - cksum += d[5]; - cksum += d[6]; - cksum += d[7]; - cksum += d[8]; - cksum += d[9]; - cksum += d[10]; - cksum += d[11]; - cksum += d[12]; - cksum += d[13]; - cksum += d[14]; - cksum += d[15]; - d += 16; - dlen -= 32; - } - - while(dlen >=8) - { - cksum += d[0]; - cksum += d[1]; - cksum += d[2]; - cksum += d[3]; - d += 4; - dlen -= 8; - } - - while(dlen > 1) - { - cksum += *d++; - dlen -= 2; - } - - if( dlen == 1 ) - { - /* printf("new checksum odd byte-packet\n"); */ - *(unsigned char*)(&answer) = (*(unsigned char*)d); - - /* cksum += (uint16_t) (*(uint8_t*)d); */ - - cksum += answer; - } - - cksum = (cksum >> 16) + (cksum & 0x0000ffff); - cksum += (cksum >> 16); - - return (unsigned short)(~cksum); -} - -/* -* checksum udp -* -* h - pseudo header - 12 bytes -* d - udp hdr + payload -* dlen - length of payload in bytes -* -*/ -static inline unsigned short in_chksum_udp6(pseudoheader6 *ph, - unsigned short * d, int dlen ) -{ - uint16_t *h = (uint16_t *)ph; - unsigned int cksum; - unsigned short answer=0; - - /* PseudoHeader must have 12 bytes */ - cksum = h[0]; - cksum += h[1]; - cksum += h[2]; - cksum += h[3]; - cksum += h[4]; - cksum += h[5]; - cksum += h[6]; - cksum += h[7]; - cksum += h[8]; - cksum += h[9]; - cksum += h[10]; - cksum += h[11]; - cksum += h[12]; - cksum += h[13]; - cksum += h[14]; - cksum += h[15]; - cksum += h[16]; - cksum += h[17]; - - /* UDP must have 8 hdr bytes */ - cksum += d[0]; - cksum += d[1]; - cksum += d[2]; - cksum += d[3]; - - dlen -= 8; /* bytes */ - d += 4; /* short's */ - - while(dlen >=32) - { - cksum += d[0]; - cksum += d[1]; - cksum += d[2]; - cksum += d[3]; - cksum += d[4]; - cksum += d[5]; - cksum += d[6]; - cksum += d[7]; - cksum += d[8]; - cksum += d[9]; - cksum += d[10]; - cksum += d[11]; - cksum += d[12]; - cksum += d[13]; - cksum += d[14]; - cksum += d[15]; - d += 16; - dlen -= 32; - } - - while(dlen >=8) - { - cksum += d[0]; - cksum += d[1]; - cksum += d[2]; - cksum += d[3]; - d += 4; - dlen -= 8; - } - - while(dlen > 1) - { - cksum += *d++; - dlen -= 2; - } - - if( dlen == 1 ) - { - *(unsigned char*)(&answer) = (*(unsigned char*)d); - cksum += answer; - } - - cksum = (cksum >> 16) + (cksum & 0x0000ffff); - cksum += (cksum >> 16); - - return (unsigned short)(~cksum); -} - - - -static inline unsigned short in_chksum_udp(pseudoheader *ph, - unsigned short * d, int dlen ) -{ - uint16_t *h = (uint16_t *)ph; - unsigned int cksum; - unsigned short answer=0; - - /* PseudoHeader must have 36 bytes */ - cksum = h[0]; - cksum += h[1]; - cksum += h[2]; - cksum += h[3]; - cksum += h[4]; - cksum += h[5]; - - /* UDP must have 8 hdr bytes */ - cksum += d[0]; - cksum += d[1]; - cksum += d[2]; - cksum += d[3]; - - dlen -= 8; /* bytes */ - d += 4; /* short's */ - - while(dlen >=32) - { - cksum += d[0]; - cksum += d[1]; - cksum += d[2]; - cksum += d[3]; - cksum += d[4]; - cksum += d[5]; - cksum += d[6]; - cksum += d[7]; - cksum += d[8]; - cksum += d[9]; - cksum += d[10]; - cksum += d[11]; - cksum += d[12]; - cksum += d[13]; - cksum += d[14]; - cksum += d[15]; - d += 16; - dlen -= 32; - } - - while(dlen >=8) - { - cksum += d[0]; - cksum += d[1]; - cksum += d[2]; - cksum += d[3]; - d += 4; - dlen -= 8; - } - - while(dlen > 1) - { - cksum += *d++; - dlen -= 2; - } - - if( dlen == 1 ) - { - *(unsigned char*)(&answer) = (*(unsigned char*)d); - cksum += answer; - } - - cksum = (cksum >> 16) + (cksum & 0x0000ffff); - cksum += (cksum >> 16); - - return (unsigned short)(~cksum); -} - -/* -* checksum icmp -*/ -static inline unsigned short in_chksum_icmp( unsigned short * w, int blen ) -{ - unsigned short answer=0; - unsigned int cksum = 0; - - while(blen >=32) - { - cksum += w[0]; - cksum += w[1]; - cksum += w[2]; - cksum += w[3]; - cksum += w[4]; - cksum += w[5]; - cksum += w[6]; - cksum += w[7]; - cksum += w[8]; - cksum += w[9]; - cksum += w[10]; - cksum += w[11]; - cksum += w[12]; - cksum += w[13]; - cksum += w[14]; - cksum += w[15]; - w += 16; - blen -= 32; - } - - while(blen >=8) - { - cksum += w[0]; - cksum += w[1]; - cksum += w[2]; - cksum += w[3]; - w += 4; - blen -= 8; - } - - while(blen > 1) - { - cksum += *w++; - blen -= 2; - } - - if( blen == 1 ) - { - *(unsigned char*)(&answer) = (*(unsigned char*)w); - cksum += answer; - } - - cksum = (cksum >> 16) + (cksum & 0x0000ffff); - cksum += (cksum >> 16); - - - return (unsigned short)(~cksum); -} - -/* -* checksum icmp6 -*/ -static inline unsigned short in_chksum_icmp6(pseudoheader6 *ph, - unsigned short *w, int blen ) -{ - uint16_t *h = (uint16_t *)ph; - unsigned short answer=0; - unsigned int cksum = 0; - - /* PseudoHeader must have 36 bytes */ - cksum = h[0]; - cksum += h[1]; - cksum += h[2]; - cksum += h[3]; - cksum += h[4]; - cksum += h[5]; - cksum += h[6]; - cksum += h[7]; - cksum += h[8]; - cksum += h[9]; - cksum += h[10]; - cksum += h[11]; - cksum += h[12]; - cksum += h[13]; - cksum += h[14]; - cksum += h[15]; - cksum += h[16]; - cksum += h[17]; - - while(blen >=32) - { - cksum += w[0]; - cksum += w[1]; - cksum += w[2]; - cksum += w[3]; - cksum += w[4]; - cksum += w[5]; - cksum += w[6]; - cksum += w[7]; - cksum += w[8]; - cksum += w[9]; - cksum += w[10]; - cksum += w[11]; - cksum += w[12]; - cksum += w[13]; - cksum += w[14]; - cksum += w[15]; - w += 16; - blen -= 32; - } - - while(blen >=8) - { - cksum += w[0]; - cksum += w[1]; - cksum += w[2]; - cksum += w[3]; - w += 4; - blen -= 8; - } - - while(blen > 1) - { - cksum += *w++; - blen -= 2; - } - - if( blen == 1 ) - { - *(unsigned char*)(&answer) = (*(unsigned char*)w); - cksum += answer; - } - - cksum = (cksum >> 16) + (cksum & 0x0000ffff); - cksum += (cksum >> 16); - - - return (unsigned short)(~cksum); -} - - -#endif /* CHECKSUM_H */ diff --git a/src/protocols/decode.cc b/src/protocols/decode.cc deleted file mode 100644 index f72f89121..000000000 --- a/src/protocols/decode.cc +++ /dev/null @@ -1,6868 +0,0 @@ -/* -** Copyright (C) 2014 Cisco and/or its affiliates. All rights reserved. -** Copyright (C) 2002-2013 Sourcefire, Inc. -** Copyright (C) 1998-2002 Martin Roesch -** -** This program is free software; you can redistribute it and/or modify -** it under the terms of the GNU General Public License Version 2 as -** published by the Free Software Foundation. You may not use, modify or -** distribute this program under any other version of the GNU General -** Public License. -** -** 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#include "decode.h" - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include -#include - -#ifdef HAVE_DUMBNET_H -#include -#else -#include -#endif - -#include "decode_module.h" -#include "analyzer.h" -#include "snort.h" -#include "snort_debug.h" -#include "util.h" -#include "detect.h" -#include "checksum.h" -#include "log_text.h" -#include "generators.h" -#include "packet_io/active.h" -#include "sfxhash.h" -#include "snort_bounds.h" -#include "sf_iph.h" -#include "fpdetect.h" -#include "profiler.h" -#include "mempool/mempool.h" -#include "normalize/normalize.h" -#include "perf_monitor/perf.h" -#include "packet_io/sfdaq.h" - -struct DecodeCounts -{ - PegCount total_processed; - PegCount eth; - PegCount vlan; - PegCount nested_vlan; - PegCount mpls; - - PegCount arp; - PegCount ip; - PegCount frags; - PegCount tcp; - PegCount udp; - PegCount icmp; - PegCount other; - - PegCount ipv6; - PegCount tcp6; - PegCount udp6; - PegCount teredo; - - PegCount ipv6_up; - PegCount ipv6_upfail; - PegCount ipv6opts; - PegCount ipv6disc; - PegCount ip6ext; - PegCount frag6; - PegCount icmp6; - - PegCount embdip; - PegCount ipx; - PegCount ethloopback; - - PegCount ip4ip4; - PegCount ip4ip6; - PegCount ip6ip4; - PegCount ip6ip6; - - PegCount gre; - PegCount gre_ip; - PegCount gre_eth; - PegCount gre_arp; - PegCount gre_ipv6; - PegCount gre_ipv6ext; - PegCount gre_ipx; - PegCount gre_loopback; - PegCount gre_vlan; - PegCount gre_ppp; - - PegCount ethdisc; - PegCount tdisc; - PegCount udisc; - PegCount icmpdisc; - PegCount ipdisc; - PegCount invalid_checksums; - PegCount bad_ttl; - PegCount discards; - -#ifndef NO_NON_ETHER_DECODER - PegCount eapol; -#ifdef DLT_IEEE802_11 - /* wireless statistics */ - PegCount wifi_mgmt; - PegCount wifi_data; - PegCount wifi_control; - PegCount assoc_req; - PegCount assoc_resp; - PegCount reassoc_req; - PegCount reassoc_resp; - PegCount probe_req; - PegCount probe_resp; - PegCount beacon; - PegCount atim; - PegCount dissassoc; - PegCount auth; - PegCount deauth; - PegCount ps_poll; - PegCount rts; - PegCount cts; - PegCount ack; - PegCount cf_end; - PegCount cf_end_cf_ack; - PegCount data; - PegCount data_cf_ack; - PegCount data_cf_poll; - PegCount data_cf_ack_cf_poll; - PegCount cf_ack; - PegCount cf_poll; - PegCount cf_ack_cf_poll; -#endif -#endif // NO_NON_ETHER_DECODER -}; - -static const char* dc_pegs[] = -{ - "total", - "eth", - "vlan", - "nested vlan", - "mpls", - - "arp", - "ip", - "frags", - "tcp", - "udp", - "icmp", - "other", - - "ipv6", - "tcp6", - "udp6", - "teredo", - - "ipv6 up", - "ipv6 upfail", - "ipv6opts", - "ipv6disc", - "ip6ext", - "frag6", - "icmp6", - - "embdip", - "ipx", - "ethloopback", - - "ip4ip4", - "ip4ip6", - "ip6ip4", - "ip6ip6", - - "gre", - "gre ip", - "gre eth", - "gre arp", - "gre ipv6", - "gre ipv6ext", - "gre ipx", - "gre loopback", - "gre vlan", - "gre ppp", - - "ethdisc", - "tcp discards", - "udp discards", - "icmp discards", - "ip discards", - "invalid checksums", - "bad ttl", - "discards", - -#ifndef NO_NON_ETHER_DECODER - "eapol", -#ifdef DLT_IEEE802_11 - /* wireless statistics */ - "wifi mgmt", - "wifi data", - "wifi control", - "assoc req", - "assoc resp", - "reassoc req", - "reassoc resp", - "probe req", - "probe resp", - "beacon", - "atim", - "dissassoc", - "auth", - "deauth", - "ps poll", - "rts", - "cts", - "ack", - "cf end", - "cf end cf ack", - "data", - "data cf ack", - "data cf poll", - "data cf ack cf poll", - "cf ack", - "cf poll", - "cf ack cf poll", -#endif -#endif // NO_NON_ETHER_DECODER -}; - -static DecodeCounts gdc; -static THREAD_LOCAL DecodeCounts dc; - -void decoder_sum() -{ - sum_stats((PegCount*)&gdc, (PegCount*)&dc, array_size(dc_pegs)); - memset(&dc, 0, sizeof(dc)); -} - -void decoder_stats() -{ - show_percent_stats((PegCount*)&gdc, dc_pegs, array_size(dc_pegs), - "decoder"); -} - -static IpAddrSet *SynToMulticastDstIp = NULL; - -#ifdef PERF_PROFILING -THREAD_LOCAL PreprocStats decodePerfStats; -#endif - -//-------------------------------------------------------------------- -// decode.c::event support -//-------------------------------------------------------------------- - -static inline int ScNormalDrop (NormFlags nf) -{ - return !Normalize_IsEnabled(snort_conf, nf); -} - -static inline void execTtlDrop (Packet* p) -{ - if ( ScNormalDrop(NORM_IP4_TTL) ) - { - DEBUG_WRAP(DebugMessage(DEBUG_DECODE, - "Dropping bad packet (IP4 TTL)\n");); - p->error_flags |= PKT_ERR_BAD_TTL; - Active_DropPacket(); - dc.bad_ttl++; - } -} - -static inline void execHopDrop (Packet* p) -{ - if ( ScNormalDrop(NORM_IP6_TTL) ) - { - DEBUG_WRAP(DebugMessage(DEBUG_DECODE, - "Dropping bad packet (IP6 hop limit)\n");); - p->error_flags |= PKT_ERR_BAD_TTL; - Active_DropPacket(); - dc.bad_ttl++; - } -} - -static inline void execIpChksmDrop (Packet*) -{ - // TBD only set policy csum drop if policy inline - // and delete this inline mode check - if( ScInlineMode() && ScIpChecksumDrops() ) - { - DEBUG_WRAP(DebugMessage(DEBUG_DECODE, - "Dropping bad packet (IP checksum)\n");); - Active_DropPacket(); - } -} - -static inline void execTcpChksmDrop (Packet*) -{ - if( ScInlineMode() && ScTcpChecksumDrops() ) - { - DEBUG_WRAP(DebugMessage(DEBUG_DECODE, - "Dropping bad packet (TCP checksum)\n");); - Active_DropPacket(); - } -} - -static inline void execUdpChksmDrop (Packet*) -{ - if( ScInlineMode() && ScUdpChecksumDrops() ) - { - DEBUG_WRAP(DebugMessage(DEBUG_DECODE, - "Dropping bad packet (UDP checksum)\n");); - Active_DropPacket(); - } -} - -static inline void execIcmpChksmDrop (Packet*) -{ - if( ScInlineMode() && ScIcmpChecksumDrops() ) - { - DEBUG_WRAP(DebugMessage(DEBUG_DECODE, - "Dropping bad packet (ICMP checksum)\n");); - Active_DropPacket(); - } -} - -static inline void DecoderEvent (Packet *p, int sid) -{ - if ( p->packet_flags & PKT_REBUILT_STREAM ) - return; - - if ( ScLogVerbose() ) - ErrorMessage("%d:%d\n", GID_DECODE, sid); - - SnortEventqAdd(GID_DECODE, sid); -} - -static inline void DecoderDrop ( - Packet *p, int sid, void (*callback)(Packet*) ) -{ - if ( p->packet_flags & PKT_REBUILT_STREAM ) - return; - - if ( ScLogVerbose() ) - ErrorMessage("%d:%d\n", GID_DECODE, sid); - - SnortEventqAdd(GID_DECODE, sid); - callback(p); -} - -void DecoderAlertEncapsulated( - Packet *p, int sid, const uint8_t *pkt, uint32_t len) -{ - DecoderEvent(p, sid); - - p->data = pkt; - p->dsize = (uint16_t)len; - - p->greh = NULL; -} - -//-------------------------------------------------------------------- -// decode.c::miscellaneous public methods and helper functions -//-------------------------------------------------------------------- - -#if defined(WORDS_MUSTALIGN) && !defined(__GNUC__) -uint32_t EXTRACT_32BITS (u_char *p) -{ - uint32_t __tmp; - - memmove(&__tmp, p, sizeof(uint32_t)); - return (uint32_t) ntohl(__tmp); -} -#endif /* WORDS_MUSTALIGN && !__GNUC__ */ - -void InitSynToMulticastDstIp( SnortConfig* sc ) -{ - SynToMulticastDstIp = IpAddrSetParse(sc, "[232.0.0.0/8,233.0.0.0/8,239.0.0.0/8]"); - - if( SynToMulticastDstIp == NULL ) - { - FatalError("Could not initialize SynToMulticastDstIp\n"); - } -} - -void SynToMulticastDstIpDestroy( void ) -{ - - if( SynToMulticastDstIp ) - { - IpAddrSetDestroy(SynToMulticastDstIp); - } -} - -static inline void CheckIPv4_MinTTL(Packet *p, uint8_t ttl) -{ - - // this sequence of tests is best for the "normal" case where - // the packet ttl is >= the configured min (the default is 1) - if( ttl < ScMinTTL() ) - { - if ( ttl == 0 ) - { - DecoderDrop(p, DECODE_ZERO_TTL, execTtlDrop); - } - else - { - DecoderDrop(p, DECODE_IP4_MIN_TTL, execTtlDrop); - } - } -} - -static inline void CheckIPv6_MinTTL(Packet *p, uint8_t hop_limit) -{ - // this sequence of tests is best for the "normal" case where - // the packet ttl is >= the configured min (the default is 1) - if( hop_limit < ScMinTTL() ) - { - if ( hop_limit == 0 ) - { - DecoderDrop(p, DECODE_IP6_ZERO_HOP_LIMIT, execHopDrop); - } - else - { - DecoderDrop(p, DECODE_IPV6_MIN_TTL, execHopDrop); - } - } -} - -/* Decoding of ttl/hop_limit is based on the policy min_ttl */ -static inline void DecodeIP_MinTTL(Packet *p) -{ - switch(p->outer_family) - { - case AF_INET: - CheckIPv4_MinTTL( p, p->outer_ip4h.ip_ttl); - return; - - case AF_INET6: - CheckIPv6_MinTTL( p, p->outer_ip6h.hop_lmt); - return; - - default: - break; - } - - switch(p->family) - { - case AF_INET: - CheckIPv4_MinTTL( p, p->ip4h->ip_ttl); - return; - - case AF_INET6: - CheckIPv6_MinTTL( p, p->ip6h->hop_lmt); - return; - - default: - break; - } - - return; -} - -// NOTE intermediate queue was eliminated in favor of directly queueing -// and checking policy before logging -// FIXIT in order for config based checks like ttl and checksum to work, -// must select decoder policy after each applicable decode (eg vlan and ip) -// (checksums use next outer layer policy; ttl use current layer policy) -// FIXIT break up and put into appropriate decoder -// NOTE new bindings are not in place yet; must stub out for now -void DecodePolicySpecific(Packet *p) -{ - DecodeIP_MinTTL(p); -} - -// this must be called iff the layer is successfully decoded because, when -// enabled, the normalizer assumes that the encoding is structurally sound -static inline void PushLayer(PROTO_ID type, Packet* p, const uint8_t* hdr, uint32_t len) -{ - if ( p->next_layer < LAYER_MAX ) - { - Layer* lyr = p->layers + p->next_layer++; - lyr->proto = type; - lyr->start = (uint8_t*)hdr; - lyr->length = (uint16_t)len; - } - else - { - LogMessage("(snort_decoder) WARNING: decoder got too many layers;" - " next proto is %u.\n", type); - } -} - -//-------------------------------------------------------------------- -// decode.c::ARP -//-------------------------------------------------------------------- - -/* - * Function: DecodeARP(uint8_t *, uint32_t, Packet *) - * - * Purpose: Decode ARP stuff - * - * Arguments: pkt => ptr to the packet data - * len => length from here to the end of the packet - * p => pointer to decoded packet struct - * - * Returns: void function - */ -void DecodeARP(const uint8_t * pkt, uint32_t len, Packet * p) -{ - dc.arp++; - - if (p->greh != NULL) - dc.gre_arp++; - - p->ah = (EtherARP *) pkt; - - if(len < sizeof(EtherARP)) - { - DecoderEvent(p, DECODE_ARP_TRUNCATED); - - dc.discards++; - return; - } - - p->proto_bits |= PROTO_BIT__ARP; - PushLayer(PROTO_ARP, p, pkt, sizeof(*p->ah)); -} - -//-------------------------------------------------------------------- -// decode.c::NULL and Loopback -//-------------------------------------------------------------------- - -/* - * Function: DecodeNullPkt(Packet *, char *, DAQ_PktHdr_t*, uint8_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, const DAQ_PktHdr_t * pkthdr, const uint8_t * pkt) -{ - uint32_t cap_len = pkthdr->caplen; - PROFILE_VARS; - - PREPROC_PROFILE_START(decodePerfStats); - - dc.total_processed++; - - memset(p, 0, PKT_ZERO_LEN); - - p->pkth = pkthdr; - p->pkt = pkt; - - DEBUG_WRAP(DebugMessage(DEBUG_DECODE, "Packet!\n"); ); - - /* do a little validation */ - if(cap_len < NULL_HDRLEN) - { - if (ScLogVerbose()) - { - ErrorMessage("NULL header length < captured len! (%d bytes)\n", - cap_len); - } - - PREPROC_PROFILE_END(decodePerfStats); - return; - } - - DecodeIP(p->pkt + NULL_HDRLEN, cap_len - NULL_HDRLEN, p); - PREPROC_PROFILE_END(decodePerfStats); -} - -/* - * Function: DecodeEthLoopback(uint8_t *, uint32_t) - * - * Purpose: Just like IPX, it's just for counting. - * - * Arguments: pkt => ptr to the packet data - * len => length from here to the end of the packet - * - * Returns: void function - */ -void DecodeEthLoopback(const uint8_t*, uint32_t, Packet *p) -{ - DEBUG_WRAP(DebugMessage(DEBUG_DECODE, "EthLoopback is not supported.\n");); - - dc.ethloopback++; - - if (p->greh != NULL) - dc.gre_loopback++; - - return; -} - -//-------------------------------------------------------------------- -// decode.c::Ethernet -//-------------------------------------------------------------------- - -/* - * Function: DecodeEthPkt(Packet *, char *, DAQ_PktHdr_t*, uint8_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, const DAQ_PktHdr_t * pkthdr, const uint8_t * pkt) -{ - uint32_t cap_len = pkthdr->caplen; - PROFILE_VARS; - - PREPROC_PROFILE_START(decodePerfStats); - dc.eth++; - dc.total_processed++; - - memset(p, 0, PKT_ZERO_LEN); - - p->pkth = pkthdr; - p->pkt = pkt; - - DEBUG_WRAP(DebugMessage(DEBUG_DECODE, "Packet!\n"); - DebugMessage(DEBUG_DECODE, "caplen: %lu pktlen: %lu\n", - (unsigned long)cap_len, (unsigned long)pkthdr->pktlen); - ); - - /* do a little validation */ - if(cap_len < ETHERNET_HEADER_LEN) - { - DEBUG_WRAP(DebugMessage(DEBUG_DECODE, - "WARNING: Truncated eth header (%d bytes).\n", cap_len);); - - DecoderEvent(p, DECODE_ETH_HDR_TRUNC); - - dc.discards++; - dc.ethdisc++; - PREPROC_PROFILE_END(decodePerfStats); - return; - } - - /* lay the ethernet structure over the packet data */ - p->eh = (EtherHdr *) pkt; - PushLayer(PROTO_ETH, p, pkt, sizeof(*p->eh)); - - DEBUG_WRAP( - DebugMessage(DEBUG_DECODE, "%X:%X:%X:%X:%X:%X -> %X:%X:%X:%X:%X:%X\n", - p->eh->ether_src[0], - p->eh->ether_src[1], p->eh->ether_src[2], p->eh->ether_src[3], - p->eh->ether_src[4], p->eh->ether_src[5], p->eh->ether_dst[0], - p->eh->ether_dst[1], p->eh->ether_dst[2], p->eh->ether_dst[3], - p->eh->ether_dst[4], p->eh->ether_dst[5]); - ); - DEBUG_WRAP( - DebugMessage(DEBUG_DECODE, "type:0x%X len:0x%X\n", - ntohs(p->eh->ether_type), p->pkth->pktlen) - ); - - /* grab out the network type */ - switch(ntohs(p->eh->ether_type)) - { - case ETHERNET_TYPE_IP: - DEBUG_WRAP( - DebugMessage(DEBUG_DECODE, - "IP datagram size calculated to be %lu bytes\n", - (unsigned long)(cap_len - ETHERNET_HEADER_LEN)); - ); - - DecodeIP(p->pkt + ETHERNET_HEADER_LEN, - cap_len - ETHERNET_HEADER_LEN, p); - - PREPROC_PROFILE_END(decodePerfStats); - return; - - case ETHERNET_TYPE_ARP: - case ETHERNET_TYPE_REVARP: - DecodeARP(p->pkt + ETHERNET_HEADER_LEN, - cap_len - ETHERNET_HEADER_LEN, p); - PREPROC_PROFILE_END(decodePerfStats); - return; - - case ETHERNET_TYPE_IPV6: - DecodeIPV6(p->pkt + ETHERNET_HEADER_LEN, - (cap_len - ETHERNET_HEADER_LEN), p); - PREPROC_PROFILE_END(decodePerfStats); - return; - - case ETHERNET_TYPE_PPPoE_DISC: - case ETHERNET_TYPE_PPPoE_SESS: - DecodePPPoEPkt(p->pkt + ETHERNET_HEADER_LEN, - (cap_len - ETHERNET_HEADER_LEN), p); - PREPROC_PROFILE_END(decodePerfStats); - return; - -#ifndef NO_NON_ETHER_DECODER - case ETHERNET_TYPE_IPX: - DecodeIPX(p->pkt + ETHERNET_HEADER_LEN, - (cap_len - ETHERNET_HEADER_LEN), p); - PREPROC_PROFILE_END(decodePerfStats); - return; -#endif - - case ETHERNET_TYPE_LOOP: - DecodeEthLoopback(p->pkt + ETHERNET_HEADER_LEN, - (cap_len - ETHERNET_HEADER_LEN), p); - PREPROC_PROFILE_END(decodePerfStats); - return; - - case ETHERNET_TYPE_8021Q: - DecodeVlan(p->pkt + ETHERNET_HEADER_LEN, - cap_len - ETHERNET_HEADER_LEN, p); - PREPROC_PROFILE_END(decodePerfStats); - return; - - case ETHERNET_TYPE_MPLS_MULTICAST: - if(!ScMplsMulticast()) - { - //additional check for DecoderAlerts will be done now. - DecoderEvent(p, DECODE_BAD_MPLS); - } - case ETHERNET_TYPE_MPLS_UNICAST: - DecodeMPLS(p->pkt + ETHERNET_HEADER_LEN, - cap_len - ETHERNET_HEADER_LEN, p); - PREPROC_PROFILE_END(decodePerfStats); - return; - - default: - // TBD add decoder drop event for unknown eth type - dc.other++; - PREPROC_PROFILE_END(decodePerfStats); - return; - } - - PREPROC_PROFILE_END(decodePerfStats); - return; -} - -/* - * Function: DecodeTransBridging(uint8_t *, const uint32_t, Packet) - * - * Purpose: Decode Transparent Ethernet Bridging - * - * Arguments: pkt => pointer to the real live packet data - * len => length of remaining data in packet - * p => pointer to the decoded packet struct - * - * - * Returns: void function - * - * Note: This is basically the code from DecodeEthPkt but the calling - * convention needed to be changed and the stuff at the beginning - * wasn't needed since we are already deep into the packet - */ -void DecodeTransBridging(const uint8_t *pkt, const uint32_t len, Packet *p) -{ - dc.gre_eth++; - - if(len < ETHERNET_HEADER_LEN) - { - DecoderAlertEncapsulated(p, DECODE_GRE_TRANS_DGRAM_LT_TRANSHDR, pkt, len); - return; - } - - /* The Packet struct's ethernet header will now point to the inner ethernet - * header of the packet - */ - p->eh = (EtherHdr *)pkt; - PushLayer(PROTO_ETH, p, pkt, sizeof(*p->eh)); - - switch (ntohs(p->eh->ether_type)) - { - case ETHERNET_TYPE_IP: - DecodeIP(pkt + ETHERNET_HEADER_LEN, len - ETHERNET_HEADER_LEN, p); - return; - - case ETHERNET_TYPE_ARP: - case ETHERNET_TYPE_REVARP: - DecodeARP(pkt + ETHERNET_HEADER_LEN, len - ETHERNET_HEADER_LEN, p); - return; - - case ETHERNET_TYPE_IPV6: - DecodeIPV6(pkt + ETHERNET_HEADER_LEN, len - ETHERNET_HEADER_LEN, p); - return; - -#ifndef NO_NON_ETHER_DECODER - case ETHERNET_TYPE_IPX: - DecodeIPX(pkt + ETHERNET_HEADER_LEN, len - ETHERNET_HEADER_LEN, p); - return; -#endif - - case ETHERNET_TYPE_LOOP: - DecodeEthLoopback(pkt + ETHERNET_HEADER_LEN, len - ETHERNET_HEADER_LEN, p); - return; - - case ETHERNET_TYPE_8021Q: - DecodeVlan(pkt + ETHERNET_HEADER_LEN, len - ETHERNET_HEADER_LEN, p); - return; - - default: - // TBD add decoder drop event for unknown xbrdg/eth type - dc.other++; - p->data = pkt + ETHERNET_HEADER_LEN; - p->dsize = (uint16_t)(len - ETHERNET_HEADER_LEN); - return; - } -} - -//-------------------------------------------------------------------- -// decode.c::MPLS -//-------------------------------------------------------------------- - -/* - * check if reserved labels are used properly - */ -static int checkMplsHdr( - uint32_t label, uint8_t, uint8_t bos, uint8_t, Packet *p) -{ - int iRet = 0; - switch(label) - { - case 0: - case 2: - /* check if this label is the bottom of the stack */ - if(bos) - { - if ( label == 0 ) - iRet = MPLS_PAYLOADTYPE_IPV4; - else if ( label == 2 ) - iRet = MPLS_PAYLOADTYPE_IPV6; - - - /* when label == 2, IPv6 is expected; - * when label == 0, IPv4 is expected */ - if((label&&(ScMplsPayloadType() != MPLS_PAYLOADTYPE_IPV6)) - ||((!label)&&(ScMplsPayloadType() != MPLS_PAYLOADTYPE_IPV4))) - { - if( !label ) - DecoderEvent(p, DECODE_BAD_MPLS_LABEL0); - else - DecoderEvent(p, DECODE_BAD_MPLS_LABEL2); - } - break; - } - -#if 0 - /* This is valid per RFC 4182. Just pop this label off, ignore it - * and move on to the next one. - */ - if( !label ) - DecoderEvent(p, DECODE_BAD_MPLS_LABEL0); - else - DecoderEvent(p, DECODE_BAD_MPLS_LABEL2); - - dc.discards++; - p->iph = NULL; - p->family = NO_IP; - return(-1); -#endif - break; - case 1: - if(!bos) break; - - DecoderEvent(p, DECODE_BAD_MPLS_LABEL1); - - dc.discards++; - p->iph = NULL; - p->family = NO_IP; - iRet = MPLS_PAYLOADTYPE_ERROR; - break; - - case 3: - DecoderEvent(p, DECODE_BAD_MPLS_LABEL3); - - dc.discards++; - p->iph = NULL; - p->family = NO_IP; - iRet = MPLS_PAYLOADTYPE_ERROR; - break; - case 4: - case 5: - case 6: - case 7: - case 8: - case 9: - case 10: - case 11: - case 12: - case 13: - case 14: - case 15: - DecoderEvent(p, DECODE_MPLS_RESERVED_LABEL); - break; - default: - break; - } - if ( !iRet ) - { - iRet = ScMplsPayloadType(); - } - return iRet; -} - -void DecodeMPLS(const uint8_t* pkt, const uint32_t len, Packet* p) -{ - uint32_t* tmpMplsHdr; - uint32_t mpls_h; - uint32_t label; - uint32_t mlen = 0; - - uint8_t exp; - uint8_t bos = 0; - uint8_t ttl; - uint8_t chainLen = 0; - uint32_t stack_len = len; - - int iRet = 0; - - dc.mpls++; - UpdateMPLSStats(&sfBase, len, Active_PacketWasDropped()); - tmpMplsHdr = (uint32_t *) pkt; - p->mpls = NULL; - - while (!bos) - { - if(stack_len < MPLS_HEADER_LEN) - { - DecoderEvent(p, DECODE_BAD_MPLS); - - dc.discards++; - p->iph = NULL; - p->family = NO_IP; - return; - } - - mpls_h = ntohl(*tmpMplsHdr); - ttl = (uint8_t)(mpls_h & 0x000000FF); - mpls_h = mpls_h>>8; - bos = (uint8_t)(mpls_h & 0x00000001); - exp = (uint8_t)(mpls_h & 0x0000000E); - label = (mpls_h>>4) & 0x000FFFFF; - - if((labelmplsHdr.label = label; - p->mplsHdr.exp = exp; - p->mplsHdr.bos = bos; - p->mplsHdr.ttl = ttl; - /** - p->mpls = &(p->mplsHdr); - **/ - p->mpls = tmpMplsHdr; - if(!iRet) - { - iRet = ScMplsPayloadType(); - } - } - tmpMplsHdr++; - stack_len -= MPLS_HEADER_LEN; - - if ((ScMplsStackDepth() != -1) && (chainLen++ >= ScMplsStackDepth())) - { - DecoderEvent(p, DECODE_MPLS_LABEL_STACK); - - dc.discards++; - p->iph = NULL; - p->family = NO_IP; - return; - } - } /* while bos not 1, peel off more labels */ - - mlen = (uint8_t*)tmpMplsHdr - pkt; - PushLayer(PROTO_MPLS, p, pkt, mlen); - mlen = len - mlen; - - switch (iRet) - { - case MPLS_PAYLOADTYPE_IPV4: - DecodeIP((uint8_t *)tmpMplsHdr, mlen, p); - break; - - case MPLS_PAYLOADTYPE_IPV6: - DecodeIPV6((uint8_t *)tmpMplsHdr, mlen, p); - break; - - case MPLS_PAYLOADTYPE_ETHERNET: - DecodeEthOverMPLS((uint8_t *)tmpMplsHdr, mlen, p); - break; - - default: - break; - } - return; -} - -void DecodeEthOverMPLS(const uint8_t* pkt, const uint32_t len, Packet* p) -{ - /* do a little validation */ - if(len < ETHERNET_HEADER_LEN) - { - if (ScLogVerbose()) - { - ErrorMessage("Captured data length < Ethernet header length!" - " (%d bytes)\n", len); - } - - p->iph = NULL; - p->family = NO_IP; - // TBD add decoder drop event for eth over MPLS cap len issue - dc.discards++; - dc.ethdisc++; - return; - } - - /* lay the ethernet structure over the packet data */ - p->eh = (EtherHdr *) pkt; // FIXTHIS squashes outer eth! - PushLayer(PROTO_ETH, p, pkt, sizeof(*p->eh)); - - DEBUG_WRAP( - DebugMessage(DEBUG_DECODE, "%X %X\n", - *p->eh->ether_src, *p->eh->ether_dst); - ); - - /* grab out the network type */ - switch(ntohs(p->eh->ether_type)) - { - case ETHERNET_TYPE_IP: - DEBUG_WRAP( - DebugMessage(DEBUG_DECODE, - "IP datagram size calculated to be %lu bytes\n", - (unsigned long)(len - ETHERNET_HEADER_LEN)); - ); - - DecodeIP(p->pkt + ETHERNET_HEADER_LEN, - len - ETHERNET_HEADER_LEN, p); - - return; - - case ETHERNET_TYPE_ARP: - case ETHERNET_TYPE_REVARP: - DecodeARP(p->pkt + ETHERNET_HEADER_LEN, - len - ETHERNET_HEADER_LEN, p); - return; - - case ETHERNET_TYPE_IPV6: - DecodeIPV6(p->pkt + ETHERNET_HEADER_LEN, - (len - ETHERNET_HEADER_LEN), p); - return; - - case ETHERNET_TYPE_PPPoE_DISC: - case ETHERNET_TYPE_PPPoE_SESS: - DecodePPPoEPkt(p->pkt + ETHERNET_HEADER_LEN, - (len - ETHERNET_HEADER_LEN), p); - return; - -#ifndef NO_NON_ETHER_DECODER - case ETHERNET_TYPE_IPX: - DecodeIPX(p->pkt + ETHERNET_HEADER_LEN, - (len - ETHERNET_HEADER_LEN), p); - return; -#endif - - case ETHERNET_TYPE_LOOP: - DecodeEthLoopback(p->pkt + ETHERNET_HEADER_LEN, - (len - ETHERNET_HEADER_LEN), p); - return; - - case ETHERNET_TYPE_8021Q: - DecodeVlan(p->pkt + ETHERNET_HEADER_LEN, - len - ETHERNET_HEADER_LEN, p); - return; - - default: - // TBD add decoder drop event for unknown mpls/eth type - dc.other++; - return; - } - - return; -} - -int isPrivateIP(uint32_t addr) -{ - switch (addr & 0xff) - { - case 0x0a: - return 1; - break; - case 0xac: - if ((addr & 0xf000) == 0x1000) - return 1; - break; - case 0xc0: - if (((addr & 0xff00) ) == 0xa800) - return 1; - break; - } - return 0; -} - -//-------------------------------------------------------------------- -// decode.c::VLAN -//-------------------------------------------------------------------- - -#define LEN_VLAN_LLC_OTHER (sizeof(VlanTagHdr) + sizeof(EthLlc) + sizeof(EthLlcOther)) - -void DecodeVlan(const uint8_t * pkt, const uint32_t len, Packet * p) -{ - dc.vlan++; - - if (p->greh != NULL) - dc.gre_vlan++; - - if(len < sizeof(VlanTagHdr)) - { - DecoderEvent(p, DECODE_BAD_VLAN); - - // TBD add decoder drop event for VLAN hdr len issue - dc.discards++; - p->iph = NULL; - p->family = NO_IP; - return; - } - - p->vh = (VlanTagHdr *) pkt; - - DEBUG_WRAP(DebugMessage(DEBUG_DECODE, "Vlan traffic:\n"); - DebugMessage(DEBUG_DECODE, " Priority: %d(0x%X)\n", - VTH_PRIORITY(p->vh), VTH_PRIORITY(p->vh)); - DebugMessage(DEBUG_DECODE, " CFI: %d\n", VTH_CFI(p->vh)); - DebugMessage(DEBUG_DECODE, " Vlan ID: %d(0x%04X)\n", - VTH_VLAN(p->vh), VTH_VLAN(p->vh)); - DebugMessage(DEBUG_DECODE, " Vlan Proto: 0x%04X\n", - ntohs(p->vh->vth_proto)); - ); - - /* check to see if we've got an encapsulated LLC layer - * http://www.geocities.com/billalexander/ethernet.html - */ - if(ntohs(p->vh->vth_proto) <= ETHERNET_MAX_LEN_ENCAP) - { - if(len < sizeof(VlanTagHdr) + sizeof(EthLlc)) - { - DecoderEvent(p, DECODE_BAD_VLAN_ETHLLC); - - dc.discards++; - p->iph = NULL; - p->family = NO_IP; - return; - } - - p->ehllc = (EthLlc *) (pkt + sizeof(VlanTagHdr)); - - DEBUG_WRAP( - DebugMessage(DEBUG_DECODE, "LLC Header:\n"); - DebugMessage(DEBUG_DECODE, " DSAP: 0x%X\n", p->ehllc->dsap); - DebugMessage(DEBUG_DECODE, " SSAP: 0x%X\n", p->ehllc->ssap); - ); - - if(p->ehllc->dsap == ETH_DSAP_IP && p->ehllc->ssap == ETH_SSAP_IP) - { - if ( len < LEN_VLAN_LLC_OTHER ) - { - DecoderEvent(p, DECODE_BAD_VLAN_OTHER); - - dc.discards++; - p->iph = NULL; - p->family = NO_IP; - - return; - } - - p->ehllcother = (EthLlcOther *) (pkt + sizeof(VlanTagHdr) + sizeof(EthLlc)); - - DEBUG_WRAP( - DebugMessage(DEBUG_DECODE, "LLC Other Header:\n"); - DebugMessage(DEBUG_DECODE, " CTRL: 0x%X\n", - p->ehllcother->ctrl); - DebugMessage(DEBUG_DECODE, " ORG: 0x%02X%02X%02X\n", - p->ehllcother->org_code[0], p->ehllcother->org_code[1], - p->ehllcother->org_code[2]); - DebugMessage(DEBUG_DECODE, " PROTO: 0x%04X\n", - ntohs(p->ehllcother->proto_id)); - ); - - PushLayer(PROTO_VLAN, p, pkt, sizeof(*p->vh)); - - switch(ntohs(p->ehllcother->proto_id)) - { - case ETHERNET_TYPE_IP: - DecodeIP(p->pkt + LEN_VLAN_LLC_OTHER, - len - LEN_VLAN_LLC_OTHER, p); - return; - - case ETHERNET_TYPE_ARP: - case ETHERNET_TYPE_REVARP: - DecodeARP(p->pkt + LEN_VLAN_LLC_OTHER, - len - LEN_VLAN_LLC_OTHER, p); - return; - - case ETHERNET_TYPE_IPV6: - DecodeIPV6(p->pkt + LEN_VLAN_LLC_OTHER, - len - LEN_VLAN_LLC_OTHER, p); - return; - - case ETHERNET_TYPE_8021Q: - dc.nested_vlan++; - DecodeVlan(p->pkt + LEN_VLAN_LLC_OTHER, - len - LEN_VLAN_LLC_OTHER, p); - return; - - case ETHERNET_TYPE_LOOP: - DecodeEthLoopback(p->pkt + LEN_VLAN_LLC_OTHER, - len - LEN_VLAN_LLC_OTHER, p); - return; - -#ifndef NO_NON_ETHER_DECODER - case ETHERNET_TYPE_IPX: - DecodeIPX(p->pkt + LEN_VLAN_LLC_OTHER, - len - LEN_VLAN_LLC_OTHER, p); - return; -#endif - - case ETHERNET_TYPE_PPPoE_DISC: - case ETHERNET_TYPE_PPPoE_SESS: - DecodePPPoEPkt(p->pkt + LEN_VLAN_LLC_OTHER, - len - LEN_VLAN_LLC_OTHER, p); - return; - - case ETHERNET_TYPE_MPLS_MULTICAST: - if(!ScMplsMulticast()) - { - DecoderEvent(p, DECODE_BAD_MPLS); - } - /* Fall through */ - case ETHERNET_TYPE_MPLS_UNICAST: - DecodeMPLS(p->pkt + LEN_VLAN_LLC_OTHER, - len - LEN_VLAN_LLC_OTHER, p); - return; - - default: - // TBD add decoder drop event for unknown vlan/eth type - dc.other++; - return; - } - } - } - else - { - PushLayer(PROTO_VLAN, p, pkt, sizeof(*p->vh)); - - 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; - - case ETHERNET_TYPE_IPV6: - DecodeIPV6(pkt +sizeof(VlanTagHdr), - len - sizeof(VlanTagHdr), p); - return; - - case ETHERNET_TYPE_8021Q: - dc.nested_vlan++; - DecodeVlan(pkt + sizeof(VlanTagHdr), - len - sizeof(VlanTagHdr), p); - return; - - case ETHERNET_TYPE_LOOP: - DecodeEthLoopback(pkt + sizeof(VlanTagHdr), - len - sizeof(VlanTagHdr), p); - return; - -#ifndef NO_NON_ETHER_DECODER - case ETHERNET_TYPE_IPX: - DecodeIPX(pkt + sizeof(VlanTagHdr), - len - sizeof(VlanTagHdr), p); - return; -#endif - - case ETHERNET_TYPE_PPPoE_DISC: - case ETHERNET_TYPE_PPPoE_SESS: - DecodePPPoEPkt(pkt + sizeof(VlanTagHdr), - len - sizeof(VlanTagHdr), p); - return; - - case ETHERNET_TYPE_MPLS_MULTICAST: - if(!ScMplsMulticast()) - { - // FIXIT should be going to event queue - SnortEventqAdd(GID_DECODE, DECODE_BAD_MPLS); - } - case ETHERNET_TYPE_MPLS_UNICAST: - DecodeMPLS(pkt + sizeof(VlanTagHdr), - len - sizeof(VlanTagHdr), p); - return; - - default: - // TBD add decoder drop event for unknown vlan/eth type - dc.other++; - return; - } - } - - // TBD add decoder drop event for unknown vlan/llc type - dc.other++; - return; -} - -//-------------------------------------------------------------------- -// decode.c::PPP related -//-------------------------------------------------------------------- - -/* - * Function: DecodePPPoEPkt(Packet *, char *, DAQ_PktHdr_t*, uint8_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(const uint8_t* pkt, const uint32_t len, Packet* p) -{ - //PPPoE_Tag *ppppoe_tag=0; - //PPPoE_Tag tag; /* needed to avoid alignment problems */ - - DEBUG_WRAP(DebugMessage(DEBUG_DECODE, "PPPoE with len: %lu\n", - (unsigned long)len);); - - /* do a little validation */ - if(len < PPPOE_HEADER_LEN) - { - DEBUG_WRAP(DebugMessage(DEBUG_DECODE, - "Captured data length < PPPoE header length! " - "(%d bytes)\n", len);); - - DecoderEvent(p, DECODE_BAD_PPPOE); - - return; - } - - DEBUG_WRAP(DebugMessage(DEBUG_DECODE, "%X %X\n", - *p->eh->ether_src, *p->eh->ether_dst);); - - /* lay the PPP over ethernet structure over the packet data */ - p->pppoeh = (PPPoEHdr *)pkt; - - /* grab out the network type */ - switch(ntohs(p->eh->ether_type)) - { - case ETHERNET_TYPE_PPPoE_DISC: - DEBUG_WRAP(DebugMessage(DEBUG_DECODE, "(PPPOE Discovery) ");); - break; - - case ETHERNET_TYPE_PPPoE_SESS: - DEBUG_WRAP(DebugMessage(DEBUG_DECODE, "(PPPOE Session) ");); - break; - - default: - return; - } - -#ifdef DEBUG_MSGS - switch(p->pppoeh->code) - { - case PPPoE_CODE_PADI: - /* The Host sends the PADI packet with the DESTINATION_ADDR set - * to the broadcast address. The CODE field is set to 0x09 and - * the SESSION_ID MUST be set to 0x0000. - * - * The PADI packet MUST contain exactly one TAG of TAG_TYPE - * Service-Name, indicating the service the Host is requesting, - * and any number of other TAG types. An entire PADI packet - * (including the PPPoE header) MUST NOT exceed 1484 octets so - * as to leave sufficient room for a relay agent to add a - * Relay-Session-Id TAG. - */ - DebugMessage(DEBUG_DECODE, "Active Discovery Initiation (PADI)\n"); - break; - - case PPPoE_CODE_PADO: - /* When the Access Concentrator receives a PADI that it can - * serve, it replies by sending a PADO packet. The - * DESTINATION_ADDR is the unicast address of the Host that - * sent the PADI. The CODE field is set to 0x07 and the - * SESSION_ID MUST be set to 0x0000. - * - * The PADO packet MUST contain one AC-Name TAG containing the - * Access Concentrator's name, a Service-Name TAG identical to - * the one in the PADI, and any number of other Service-Name - * TAGs indicating other services that the Access Concentrator - * offers. If the Access Concentrator can not serve the PADI - * it MUST NOT respond with a PADO. - */ - DebugMessage(DEBUG_DECODE, "Active Discovery Offer (PADO)\n"); - break; - - case PPPoE_CODE_PADR: - /* Since the PADI was broadcast, the Host may receive more than - * one PADO. The Host looks through the PADO packets it receives - * and chooses one. The choice can be based on the AC-Name or - * the Services offered. The Host then sends one PADR packet - * to the Access Concentrator that it has chosen. The - * DESTINATION_ADDR field is set to the unicast Ethernet address - * of the Access Concentrator that sent the PADO. The CODE - * field is set to 0x19 and the SESSION_ID MUST be set to 0x0000. - * - * The PADR packet MUST contain exactly one TAG of TAG_TYPE - * Service-Name, indicating the service the Host is requesting, - * and any number of other TAG types. - */ - DebugMessage(DEBUG_DECODE, "Active Discovery Request (PADR)\n"); - break; - - case PPPoE_CODE_PADS: - /* When the Access Concentrator receives a PADR packet, it - * prepares to begin a PPP session. It generates a unique - * SESSION_ID for the PPPoE session and replies to the Host with - * a PADS packet. The DESTINATION_ADDR field is the unicast - * Ethernet address of the Host that sent the PADR. The CODE - * field is set to 0x65 and the SESSION_ID MUST be set to the - * unique value generated for this PPPoE session. - * - * The PADS packet contains exactly one TAG of TAG_TYPE - * Service-Name, indicating the service under which Access - * Concentrator has accepted the PPPoE session, and any number - * of other TAG types. - * - * If the Access Concentrator does not like the Service-Name in - * the PADR, then it MUST reply with a PADS containing a TAG of - * TAG_TYPE Service-Name-Error (and any number of other TAG - * types). In this case the SESSION_ID MUST be set to 0x0000. - */ - DebugMessage(DEBUG_DECODE, "Active Discovery " - "Session-confirmation (PADS)\n"); - break; - - case PPPoE_CODE_PADT: - /* This packet may be sent anytime after a session is established - * to indicate that a PPPoE session has been terminated. It may - * be sent by either the Host or the Access Concentrator. The - * DESTINATION_ADDR field is a unicast Ethernet address, the - * CODE field is set to 0xa7 and the SESSION_ID MUST be set to - * indicate which session is to be terminated. No TAGs are - * required. - * - * When a PADT is received, no further PPP traffic is allowed to - * be sent using that session. Even normal PPP termination - * packets MUST NOT be sent after sending or receiving a PADT. - * A PPP peer SHOULD use the PPP protocol itself to bring down a - * PPPoE session, but the PADT MAY be used when PPP can not be - * used. - */ - DebugMessage(DEBUG_DECODE, "Active Discovery Terminate (PADT)\n"); - break; - - case PPPoE_CODE_SESS: - DebugMessage(DEBUG_DECODE, "Session Packet (SESS)\n"); - break; - - default: - DebugMessage(DEBUG_DECODE, "(Unknown)\n"); - break; - } -#endif - - if (ntohs(p->eh->ether_type) != ETHERNET_TYPE_PPPoE_DISC) - { - PushLayer(PROTO_PPPOE, p, pkt, PPPOE_HEADER_LEN); - DecodePppPktEncapsulated(pkt + PPPOE_HEADER_LEN, len - PPPOE_HEADER_LEN, p); - return; - } - else - { - DEBUG_WRAP(DebugMessage(DEBUG_DECODE, "Returning early on PPPOE discovery packet\n");); - return; - } - -#if 0 - ppppoe_tag = (PPPoE_Tag *)(pkt + sizeof(PPPoEHdr)); - - while (ppppoe_tag < (PPPoE_Tag *)(pkt + len)) - { - if (((char*)(ppppoe_tag)+(sizeof(PPPoE_Tag)-1)) > (char*)(pkt + len)) - { - DEBUG_WRAP(DebugMessage(DEBUG_DECODE, "Not enough data in packet for PPPOE Tag\n");); - break; - } - - /* no guarantee in PPPoE spec that ppppoe_tag is aligned at all... */ - memcpy(&tag, ppppoe_tag, sizeof(tag)); - - DEBUG_WRAP( - DebugMessage(DEBUG_DECODE, "\tPPPoE tag:\ntype: %04x length: %04x ", - ntohs(tag.type), ntohs(tag.length));); - -#ifdef DEBUG_MSGS - switch(ntohs(tag.type)) - { - case PPPoE_TAG_END_OF_LIST: - DebugMessage(DEBUG_DECODE, "(End of list)\n\t"); - break; - case PPPoE_TAG_SERVICE_NAME: - DebugMessage(DEBUG_DECODE, "(Service name)\n\t"); - break; - case PPPoE_TAG_AC_NAME: - DebugMessage(DEBUG_DECODE, "(AC Name)\n\t"); - break; - case PPPoE_TAG_HOST_UNIQ: - DebugMessage(DEBUG_DECODE, "(Host Uniq)\n\t"); - break; - case PPPoE_TAG_AC_COOKIE: - DebugMessage(DEBUG_DECODE, "(AC Cookie)\n\t"); - break; - case PPPoE_TAG_VENDOR_SPECIFIC: - DebugMessage(DEBUG_DECODE, "(Vendor Specific)\n\t"); - break; - case PPPoE_TAG_RELAY_SESSION_ID: - DebugMessage(DEBUG_DECODE, "(Relay Session ID)\n\t"); - break; - case PPPoE_TAG_SERVICE_NAME_ERROR: - DebugMessage(DEBUG_DECODE, "(Service Name Error)\n\t"); - break; - case PPPoE_TAG_AC_SYSTEM_ERROR: - DebugMessage(DEBUG_DECODE, "(AC System Error)\n\t"); - break; - case PPPoE_TAG_GENERIC_ERROR: - DebugMessage(DEBUG_DECODE, "(Generic Error)\n\t"); - break; - default: - DebugMessage(DEBUG_DECODE, "(Unknown)\n\t"); - break; - } -#endif - -#ifdef DEBUG_MSGS - if (ntohs(tag.length) > 0) - { - char *buf; - int i; - - switch (ntohs(tag.type)) - { - case PPPoE_TAG_SERVICE_NAME: - case PPPoE_TAG_AC_NAME: - case PPPoE_TAG_SERVICE_NAME_ERROR: - case PPPoE_TAG_AC_SYSTEM_ERROR: - case PPPoE_TAG_GENERIC_ERROR: * ascii data * - buf = (char *)SnortAlloc(ntohs(tag.length) + 1); - strlcpy(buf, (char *)(ppppoe_tag+1), ntohs(tag.length)); - DebugMessage(DEBUG_DECODE, "data (UTF-8): %s\n", buf); - free(buf); - break; - - case PPPoE_TAG_HOST_UNIQ: - case PPPoE_TAG_AC_COOKIE: - case PPPoE_TAG_RELAY_SESSION_ID: - DebugMessage(DEBUG_DECODE, "data (bin): "); - for (i = 0; i < ntohs(tag.length); i++) - DebugMessage(DEBUG_DECODE, - "%02x", *(((unsigned char *)ppppoe_tag) + - sizeof(PPPoE_Tag) + i)); - DebugMessage(DEBUG_DECODE, "\n"); - break; - - default: - DebugMessage(DEBUG_DECODE, "unrecognized data\n"); - break; - } - } -#endif - - ppppoe_tag = (PPPoE_Tag *)((char *)(ppppoe_tag+1)+ntohs(tag.length)); - } - -#endif /* #if 0 */ - - return; -} - -/* - * Function: DecodePppPktEncapsulated(Packet *, const uint32_t len, uint8_t*) - * - * Purpose: Decode PPP traffic (RFC1661 framing). - * - * Arguments: p => pointer to decoded packet struct - * len => length of data to process - * pkt => pointer to the real live packet data - * - * Returns: void function - */ -void DecodePppPktEncapsulated(const uint8_t* pkt, const uint32_t len, Packet* p) -{ - static THREAD_LOCAL int had_vj = 0; - uint16_t protocol; - uint32_t hlen = 1; /* HEADER - try 1 then 2 */ - - DEBUG_WRAP(DebugMessage(DEBUG_DECODE, "PPP Packet!\n");); - -#ifdef WORDS_MUSTALIGN - DEBUG_WRAP(DebugMessage(DEBUG_DECODE, "Packet with PPP header. " - "PPP is only 1 or 2 bytes and will throw off " - "alignment on this architecture when decoding IP, " - "causing a bus error - stop decoding packet.\n");); - - p->data = pkt; - p->dsize = (uint16_t)len; - return; -#endif /* WORDS_MUSTALIGN */ - - if (p->greh != NULL) - dc.gre_ppp++; - - /* do a little validation: - * - */ - if(len < 2) - { - if (ScLogVerbose()) - { - ErrorMessage("Length not big enough for even a single " - "header or a one byte payload\n"); - } - return; - } - - - if(pkt[0] & 0x01) - { - /* Check for protocol compression rfc1661 section 5 - * - */ - hlen = 1; - protocol = pkt[0]; - } - else - { - protocol = ntohs(*((uint16_t *)pkt)); - hlen = 2; - } - - /* - * We only handle uncompressed packets. Handling VJ compression would mean - * to implement a PPP state machine. - */ - switch (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(len < (hlen + IP_HEADER_LEN)) - { - if (ScLogVerbose()) - ErrorMessage("PPP VJ min packet length > captured len! " - "(%d bytes)\n", len); - return; - } - - ((IPHdr *)(pkt + hlen))->ip_proto = IPPROTO_TCP; - /* fall through */ - - case PPP_IP: - PushLayer(PROTO_PPP_ENCAP, p, pkt, hlen); - DecodeIP(pkt + hlen, len - hlen, p); - break; - - case PPP_IPV6: - PushLayer(PROTO_PPP_ENCAP, p, pkt, hlen); - DecodeIPV6(pkt + hlen, len - hlen, p); - break; - -#ifndef NO_NON_ETHER_DECODER - case PPP_IPX: - PushLayer(PROTO_PPP_ENCAP, p, pkt, hlen); - DecodeIPX(pkt + hlen, len - hlen, p); - break; -#endif - } -} - -//-------------------------------------------------------------------- -// decode.c::Raw packets -//-------------------------------------------------------------------- - -/* - * Function: DecodeRawPkt(Packet *, char *, DAQ_PktHdr_t*, uint8_t*) - * - * Purpose: Decodes packets coming in raw on layer 2, like PPP. Coded and - * in by Jed Pickle (thanks Jed!) and modified for a few little tweaks - * by me. - * - * Arguments: p => pointer to decoded packet struct - * pkthdr => ptr to the packet header - * pkt => pointer to the real live packet data - * - * Returns: void function - */ -void DecodeRawPkt(Packet * p, const DAQ_PktHdr_t * pkthdr, const uint8_t * pkt) -{ - PROFILE_VARS; - - PREPROC_PROFILE_START(decodePerfStats); - - dc.total_processed++; - - memset(p, 0, PKT_ZERO_LEN); - - p->pkth = pkthdr; - p->pkt = pkt; - - DEBUG_WRAP(DebugMessage(DEBUG_DECODE, "Raw IP4 Packet!\n");); - - DecodeIP(pkt, p->pkth->caplen, p); - - PREPROC_PROFILE_END(decodePerfStats); - return; -} - -// raw packets are predetermined to be ip4 (above) or ip6 (below) by the DLT - -void DecodeRawPkt6(Packet * p, const DAQ_PktHdr_t * pkthdr, const uint8_t * pkt) -{ - PROFILE_VARS; - PREPROC_PROFILE_START(decodePerfStats); - - dc.total_processed++; - memset(p, 0, PKT_ZERO_LEN); - - p->pkth = pkthdr; - p->pkt = pkt; - - DEBUG_WRAP(DebugMessage(DEBUG_DECODE, "Raw IP6 Packet!\n");); - - DecodeIPV6(pkt, p->pkth->caplen, p); - - PREPROC_PROFILE_END(decodePerfStats); - return; -} - -//-------------------------------------------------------------------- -// decode.c::IP4 misc -//-------------------------------------------------------------------- - -/* - * Some IP Header tests - * Land Attack(same src/dst ip) - * Loopback (src or dst in 127/8 block) - * Modified: 2/22/05-man for High Endian Architecture. - */ -#define IP4_THIS_NET 0x00 // msb -#define IP4_MULTICAST 0x0E // ms nibble -#define IP4_RESERVED 0x0F // ms nibble -#define IP4_LOOPBACK 0x7F // msb -#define IP4_BROADCAST 0xffffffff - -void IP4AddrTests (Packet* p) -{ - uint8_t msb_src, msb_dst; - - // check all 32 bits ... - if( p->iph->ip_src.s_addr == p->iph->ip_dst.s_addr ) - { - DecoderEvent(p, DECODE_BAD_TRAFFIC_SAME_SRCDST); - - } - - // check all 32 bits ... - if ( p->iph->ip_src.s_addr == IP4_BROADCAST ) - DecoderEvent(p, DECODE_IP4_SRC_BROADCAST); - - if ( p->iph->ip_dst.s_addr == IP4_BROADCAST ) - DecoderEvent(p, DECODE_IP4_DST_BROADCAST); - - /* Loopback traffic - don't use htonl for speed reasons - - * s_addr is always in network order */ -#ifdef WORDS_BIGENDIAN - msb_src = (p->iph->ip_src.s_addr >> 24); - msb_dst = (p->iph->ip_dst.s_addr >> 24); -#else - msb_src = (uint8_t)(p->iph->ip_src.s_addr & 0xff); - msb_dst = (uint8_t)(p->iph->ip_dst.s_addr & 0xff); -#endif - // check the msb ... - if ( msb_src == IP4_LOOPBACK || msb_dst == IP4_LOOPBACK ) - { - DecoderEvent(p, DECODE_BAD_TRAFFIC_LOOPBACK); - } - // check the msb ... - if ( msb_src == IP4_THIS_NET ) - DecoderEvent(p, DECODE_IP4_SRC_THIS_NET); - - if ( msb_dst == IP4_THIS_NET ) - DecoderEvent(p, DECODE_IP4_DST_THIS_NET); - - // check the 'msn' (most significant nibble) ... - msb_src >>= 4; - msb_dst >>= 4; - - if ( msb_src == IP4_MULTICAST ) - DecoderEvent(p, DECODE_IP4_SRC_MULTICAST); - - if ( msb_src == IP4_RESERVED ) - DecoderEvent(p, DECODE_IP4_SRC_RESERVED); - - if ( msb_dst == IP4_RESERVED ) - DecoderEvent(p, DECODE_IP4_DST_RESERVED); -} - -static inline void ICMP4AddrTests (Packet* p) -{ - uint8_t msb_dst; - - uint32_t dst = GET_DST_IP(p)->ip32[0]; - - // check all 32 bits; all set so byte order is irrelevant ... - if ( dst == IP4_BROADCAST ) - DecoderEvent(p, DECODE_ICMP4_DST_BROADCAST); - - /* - don't use htonl for speed reasons - - * s_addr is always in network order */ -#ifdef WORDS_BIGENDIAN - msb_dst = (uint8_t)(dst >> 24); -#else - msb_dst = (uint8_t)(dst & 0xff); -#endif - - // check the 'msn' (most significant nibble) ... - msb_dst >>= 4; - - if ( msb_dst == IP4_MULTICAST ) - DecoderEvent(p, DECODE_ICMP4_DST_MULTICAST); -} - -static inline void ICMP4MiscTests (Packet *p) -{ - { - if ((p->dsize == 0) && - (p->icmph->type == ICMP_ECHO)) - DecoderEvent(p, DECODE_ICMP_PING_NMAP); - } - - { - if ((p->dsize == 0) && - (p->icmph->s_icmp_seq == 666)) - DecoderEvent(p, DECODE_ICMP_ICMPENUM); - } - - { - if ((p->icmph->code == 1) && - (p->icmph->type == ICMP_REDIRECT)) - DecoderEvent(p, DECODE_ICMP_REDIRECT_HOST); - } - - { - if ((p->icmph->type == ICMP_REDIRECT) && - (p->icmph->code == 0)) - DecoderEvent(p, DECODE_ICMP_REDIRECT_NET); - } - - { - if (p->icmph->type == ICMP_ECHOREPLY) - { - int i; - for (i = 0; i < p->ip_option_count; i++) - { - if (p->ip_options[i].code == IPOPT_RR) - DecoderEvent(p, DECODE_ICMP_TRACEROUTE_IPOPTS); - } - } - } - - { - if ((p->icmph->type == ICMP_SOURCE_QUENCH) && - (p->icmph->code == 0)) - DecoderEvent(p, DECODE_ICMP_SOURCE_QUENCH); - } - - { - if ((p->dsize == 4) && - (p->icmph->type == ICMP_ECHO) && - (p->icmph->s_icmp_seq == 0) && - (p->icmph->code == 0)) - DecoderEvent(p, DECODE_ICMP_BROADSCAN_SMURF_SCANNER); - } - - { - if ((p->icmph->type == ICMP_DEST_UNREACH) && - (p->icmph->code == 13)) - DecoderEvent(p, DECODE_ICMP_DST_UNREACH_ADMIN_PROHIBITED); - } - - { - if ((p->icmph->type == ICMP_DEST_UNREACH) && - (p->icmph->code == 10)) - DecoderEvent(p, DECODE_ICMP_DST_UNREACH_DST_HOST_PROHIBITED); - } - - { - if ((p->icmph->type == ICMP_DEST_UNREACH) && - (p->icmph->code == 9)) - DecoderEvent(p, DECODE_ICMP_DST_UNREACH_DST_NET_PROHIBITED); - } - -} - -/* IPv4-layer decoder rules */ -static inline void IPMiscTests(Packet *p) -{ - { - /* Yes, it's an ICMP-related vuln in IP options. */ - uint8_t i, length, pointer; - - /* Alert on IP packets with either 0x07 (Record Route) or 0x44 (Timestamp) - options that are specially crafted. */ - for (i = 0; i < p->ip_option_count; i++) - { - if (p->ip_options[i].data == NULL) - continue; - - if (p->ip_options[i].code == IPOPT_RR) - { - length = p->ip_options[i].len; - if (length < 1) - continue; - - pointer = p->ip_options[i].data[0]; - - /* If the pointer goes past the end of the data, then the data - is full. That's okay. */ - if (pointer >= length + 2) - continue; - /* If the remaining space in the option isn't a multiple of 4 - bytes, alert. */ - if (((length + 3) - pointer) % 4) - DecoderEvent(p, DECODE_ICMP_DOS_ATTEMPT); - } - else if (p->ip_options[i].code == IPOPT_TS) - { - length = p->ip_options[i].len; - if (length < 2) - continue; - - pointer = p->ip_options[i].data[0]; - - /* If the pointer goes past the end of the data, then the data - is full. That's okay. */ - if (pointer >= length + 2) - continue; - /* If the remaining space in the option isn't a multiple of 4 - bytes, alert. */ - if (((length + 3) - pointer) % 4) - DecoderEvent(p, DECODE_ICMP_DOS_ATTEMPT); - /* If there is a timestamp + address, we need a multiple of 8 - bytes instead. */ - if ((p->ip_options[i].data[1] & 0x01) && /* address flag */ - (((length + 3) - pointer) % 8)) - DecoderEvent(p, DECODE_ICMP_DOS_ATTEMPT); - } - } - } - { - if (p->ip_option_count > 0) - DecoderEvent(p, DECODE_IP_OPTION_SET); - } - - { - if (p->rf) - DecoderEvent(p, DECODE_IP_RESERVED_FRAG_BIT); - } -} - -//-------------------------------------------------------------------- -// decode.c::IP4 vulnerabilities -//-------------------------------------------------------------------- - -/* This PGM NAK function started off as an SO rule, sid 8351. */ -static inline int pgm_nak_detect (uint8_t *data, uint16_t length) { - uint16_t data_left; - uint16_t checksum; - PGM_HEADER *header; - - if (NULL == data) { - return PGM_NAK_ERR; - } - - /* request must be bigger than 44 bytes to cause vuln */ - if (length <= sizeof(PGM_HEADER)) { - return PGM_NAK_ERR; - } - - header = (PGM_HEADER *) data; - - if (8 != header->type) { - return PGM_NAK_ERR; - } - - if (2 != header->nak.opt.type) { - return PGM_NAK_ERR; - } - - - /* - * alert if the amount of data after the options is more than the length - * specified. - */ - - - data_left = length - 36; - if (data_left > header->nak.opt.len) { - - /* checksum is expensive... do that only if the length is bad */ - if (header->checksum != 0) { - checksum = in_chksum_ip((unsigned short*)data, (int)length); - if (checksum != 0) - return PGM_NAK_ERR; - } - - return PGM_NAK_VULN; - } - - return PGM_NAK_OK; -} - -static inline void CheckPGMVuln(Packet *p) -{ - if ( pgm_nak_detect((uint8_t *)p->data, p->dsize) == PGM_NAK_VULN ) - DecoderEvent(p, DECODE_PGM_NAK_OVERFLOW); -} - -/* This function is a port of an old .so rule, sid 3:8092. */ -static inline void CheckIGMPVuln(Packet *p) -{ - int i, alert = 0; - - if (p->dsize >= 1 && p->data[0] == 0x11) - { - if (p->ip_options_data != NULL) { - if (p->ip_options_len >= 2) { - if (*(p->ip_options_data) == 0 && *(p->ip_options_data+1) == 0) - { - DecoderEvent(p, DECODE_IGMP_OPTIONS_DOS); - return; - } - } - } - - for(i=0; i< (int) p->ip_option_count; i++) { - /* All IGMPv2 packets contain IP option code 148 (router alert). - This vulnerability only applies to IGMPv3, so return early. */ - if (p->ip_options[i].code == 148) { - return; /* No alert. */ - } - - if (p->ip_options[i].len == 1) { - alert++; - } - } - - if (alert > 0) - DecoderEvent(p, DECODE_IGMP_OPTIONS_DOS); - } -} - -//-------------------------------------------------------------------- -// decode.c::IP4 decoder -//-------------------------------------------------------------------- - -/* Function: DecodeIPv4Proto - * - * Gernalized IPv4 next protocol decoder dispatching. - * - * Arguments: proto => IPPROTO value of the next protocol - * pkt => ptr to the packet data - * len => length from here to the end of the packet - * p => pointer to the packet decode struct - * - */ -static inline void DecodeIPv4Proto(const uint8_t proto, - const uint8_t *pkt, const uint32_t len, Packet *p) -{ - switch(proto) - { - case IPPROTO_TCP: - dc.tcp++; - DecodeTCP(pkt, len, p); - return; - - case IPPROTO_UDP: - dc.udp++; - DecodeUDP(pkt, len, p); - return; - - case IPPROTO_ICMP: - dc.icmp++; - DecodeICMP(pkt, len, p); - return; - - case IPPROTO_IPV6: - if (len < 40) - { - /* Insufficient size for IPv6 Header. */ - /* This could be an attempt to exploit Linux kernel - * vulnerability, so log an alert */ - DecoderEvent(p, DECODE_IPV6_TUNNELED_IPV4_TRUNCATED); - } - dc.ip4ip6++; - if ( ScTunnelBypassEnabled(TUNNEL_6IN4) ) - Active_SetTunnelBypass(); - DecodeIPV6(pkt, len, p); - return; - - case IPPROTO_GRE: - dc.gre++; - DecodeGRE(pkt, len, p); - return; - - case IPPROTO_IPIP: - dc.ip4ip4++; - DecodeIP(pkt, len, p); - return; - - case IPPROTO_ESP: - if (ScESPDecoding()) - DecodeESP(pkt, len, p); - return; - - case IPPROTO_AH: - DecodeAH(pkt, len, p); - return; - - case IPPROTO_SWIPE: - case IPPROTO_IP_MOBILITY: - case IPPROTO_SUN_ND: - case IPPROTO_PIM: - DecoderEvent(p, DECODE_IP_BAD_PROTO); - dc.other++; - p->data = pkt; - p->dsize = (uint16_t)len; - return; - - case IPPROTO_PGM: - dc.other++; - p->data = pkt; - p->dsize = (uint16_t)len; - CheckPGMVuln(p); - return; - - case IPPROTO_IGMP: - dc.other++; - p->data = pkt; - p->dsize = (uint16_t)len; - CheckIGMPVuln(p); - return; - - default: - { - if (GET_IPH_PROTO(p) >= MIN_UNASSIGNED_IP_PROTO) - DecoderEvent(p, DECODE_IP_UNASSIGNED_PROTO); - } - dc.other++; - p->data = pkt; - p->dsize = (uint16_t)len; - return; - } -} - -/* - * Function: DecodeIP(uint8_t *, const uint32_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(const uint8_t * pkt, const uint32_t len, Packet * p) -{ - uint32_t ip_len; /* length from the start of the ip hdr to the pkt end */ - uint32_t hlen; /* ip header length */ - - dc.ip++; - - if (p->greh != NULL) - dc.gre_ip++; - - DEBUG_WRAP(DebugMessage(DEBUG_DECODE, "Packet!\n");); - - /* do a little validation */ - if(len < IP_HEADER_LEN) - { - DEBUG_WRAP(DebugMessage(DEBUG_DECODE, - "WARNING: Truncated IP4 header (%d bytes).\n", len);); - - DecoderEvent(p, DECODE_IP4_HDR_TRUNC); - - p->iph = NULL; - p->family = NO_IP; - - dc.discards++; - dc.ipdisc++; - return; - } - - if (p->family != NO_IP) - { - if (p->encapsulated) - { - DecoderAlertEncapsulated(p, DECODE_IP_MULTIPLE_ENCAPSULATION, pkt, len); - - return; - } - else - { - p->encapsulated = 1; - p->outer_iph = p->iph; - p->outer_ip_data = p->ip_data; - p->outer_ip_dsize = p->ip_dsize; - } - } - - /* lay the IP struct over the raw data */ - p->inner_iph = p->iph = (IPHdr *)pkt; - - /* - * with datalink DLT_RAW it's impossible to differ ARP datagrams from IP. - * So we are just ignoring non IP datagrams - */ - if(IP_VER((IPHdr*)pkt) != 4) - { - if ((p->packet_flags & PKT_UNSURE_ENCAP) == 0) - DecoderEvent(p, DECODE_NOT_IPV4_DGRAM); - - p->iph = NULL; - p->family = NO_IP; - - dc.discards++; - dc.ipdisc++; - return; - } - - sfiph_build(p, p->iph, AF_INET); - - /* get the IP datagram length */ - ip_len = ntohs(p->iph->ip_len); - - /* get the IP header length */ - hlen = IP_HLEN(p->iph) << 2; - - /* header length sanity check */ - if(hlen < IP_HEADER_LEN) - { - DEBUG_WRAP(DebugMessage(DEBUG_DECODE, - "Bogus IP header length of %i bytes\n", hlen);); - - DecoderEvent(p, DECODE_IPV4_INVALID_HEADER_LEN); - - p->iph = NULL; - p->family = NO_IP; - - dc.discards++; - dc.ipdisc++; - return; - } - - if (ip_len > len) - { - DEBUG_WRAP(DebugMessage(DEBUG_DECODE, - "IP Len field is %d bytes bigger than captured length.\n" - " (ip.len: %lu, cap.len: %lu)\n", - ip_len - len, ip_len, len);); - - DecoderEvent(p, DECODE_IPV4_DGRAM_GT_CAPLEN); - - p->iph = NULL; - p->family = NO_IP; - - dc.discards++; - dc.ipdisc++; - return; - } -#if 0 - // There is no need to alert when (ip_len < len). - // Libpcap will capture more bytes than are part of the IP payload. - // These could be Ethernet trailers, ESP trailers, etc. - // This code is left in, commented, to keep us from re-writing it later. - else if (ip_len < len) - { - if (ScLogVerbose()) - ErrorMessage("IP Len field is %d bytes " - "smaller than captured length.\n" - " (ip.len: %lu, cap.len: %lu)\n", - len - ip_len, ip_len, len); - } -#endif - - if(ip_len < hlen) - { - DEBUG_WRAP(DebugMessage(DEBUG_DECODE, - "IP dgm len (%d bytes) < IP hdr " - "len (%d bytes), packet discarded\n", ip_len, hlen);); - - DecoderEvent(p, DECODE_IPV4_DGRAM_LT_IPHDR); - - p->iph = NULL; - p->family = NO_IP; - - dc.discards++; - dc.ipdisc++; - return; - } - - /* - * IP Header tests: Land attack, and Loop back test - */ - IP4AddrTests(p); - - if (ScIpChecksums()) - { - /* routers drop packets with bad IP checksums, we don't really - * need to check them (should make this a command line/config - * option - */ - int16_t csum = in_chksum_ip((u_short *)p->iph, hlen); - - if(csum) - { - p->error_flags |= PKT_ERR_CKSUM_IP; - DEBUG_WRAP(DebugMessage(DEBUG_DECODE, "Bad IP checksum\n");); - - execIpChksmDrop(p); - dc.invalid_checksums++; - } -#ifdef DEBUG_MSGS - else - { - DebugMessage(DEBUG_DECODE, "IP Checksum: OK\n"); - } -#endif /* DEBUG */ - } - - PushLayer(PROTO_IP4, p, pkt, hlen); - - /* test for IP options */ - p->ip_options_len = (uint16_t)(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 - { - /* If delivery header for GRE encapsulated packet is IP and it - * had options, the packet's ip options will be refering to this - * outer IP's options - * Zero these options so they aren't associated with this inner IP - * since p->iph will be pointing to this inner IP - */ - if (p->encapsulated) - { - p->ip_options_data = NULL; - p->ip_options_len = 0; - } - p->ip_option_count = 0; - } - - /* set the real IP length for logging */ - p->actual_ip_len = (uint16_t) ip_len; - - /* 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 - */ - p->rf = (uint8_t)((p->frag_offset & 0x8000) >> 15); - p->df = (uint8_t)((p->frag_offset & 0x4000) >> 14); - p->mf = (uint8_t)((p->frag_offset & 0x2000) >> 13); - - /* mask off the high bits in the fragment offset field */ - p->frag_offset &= 0x1FFF; - - if ( p->df && p->frag_offset ) - DecoderEvent(p, DECODE_IP4_DF_OFFSET); - - if ( p->frag_offset + p->actual_ip_len > IP_MAXPACKET ) - DecoderEvent(p, DECODE_IP4_LEN_OFFSET); - - if(p->frag_offset || p->mf) - { - if ( !ip_len ) - { - DecoderEvent(p, DECODE_ZERO_LENGTH_FRAG); - p->frag_flag = 0; - } - else - { - /* set the packet fragment flag */ - p->frag_flag = 1; - p->ip_frag_start = pkt + hlen; - p->ip_frag_len = (uint16_t)ip_len; - dc.frags++; - } - } - else - { - p->frag_flag = 0; - } - - { - - if( p->mf && p->df ) - { - DecoderEvent(p, DECODE_BAD_FRAGBITS); - } - } - - /* Set some convienience pointers */ - p->ip_data = pkt + hlen; - p->ip_dsize = (u_short) ip_len; - - /* See if there are any ip_proto only rules that match */ - fpEvalIpProtoOnlyRules(snort_conf->ip_proto_only_lists, p); - - p->proto_bits |= PROTO_BIT__IP; - - IPMiscTests(p); - - /* if this packet isn't a fragment - * or if it is, its a UDP packet and offset is 0 */ - if(!(p->frag_flag) || - (p->frag_flag && (p->frag_offset == 0) && - (p->iph->ip_proto == IPPROTO_UDP))) - { - DEBUG_WRAP(DebugMessage(DEBUG_DECODE, "IP header length: %lu\n", - (unsigned long)hlen);); - - DecodeIPv4Proto(p->iph->ip_proto, pkt+hlen, ip_len, p); - } - else - { - /* set the payload pointer and payload size */ - p->data = pkt + hlen; - p->dsize = (u_short) ip_len; - } -} - -//-------------------------------------------------------------------- -// decode.c::ICMP -//-------------------------------------------------------------------- - -/* - * Function: DecodeICMP(uint8_t *, const uint32_t, Packet *) - * - * Purpose: Decode the ICMP transport layer - * - * Arguments: pkt => ptr to the packet data - * len => length from here to the end of the packet - * p => pointer to the decoded packet struct - * - * Returns: void function - */ -void DecodeICMP(const uint8_t * pkt, const uint32_t len, Packet * p) -{ - if(len < ICMP_HEADER_LEN) - { - DEBUG_WRAP(DebugMessage(DEBUG_DECODE, - "WARNING: Truncated ICMP4 header (%d bytes).\n", len);); - - DecoderEvent(p, DECODE_ICMP4_HDR_TRUNC); - - p->icmph = NULL; - dc.discards++; - dc.icmpdisc++; - - return; - } - - /* set the header ptr first */ - p->icmph = (ICMPHdr *) pkt; - - switch (p->icmph->type) - { - // fall through ... - case ICMP_SOURCE_QUENCH: - case ICMP_DEST_UNREACH: - case ICMP_REDIRECT: - case ICMP_TIME_EXCEEDED: - case ICMP_PARAMETERPROB: - case ICMP_ECHOREPLY: - case ICMP_ECHO: - case ICMP_ROUTER_ADVERTISE: - case ICMP_ROUTER_SOLICIT: - case ICMP_INFO_REQUEST: - case ICMP_INFO_REPLY: - if (len < 8) - { - DEBUG_WRAP(DebugMessage(DEBUG_DECODE, - "Truncated ICMP header(%d bytes)\n", len);); - - DecoderEvent(p, DECODE_ICMP_DGRAM_LT_ICMPHDR); - - p->icmph = NULL; - dc.discards++; - dc.icmpdisc++; - - return; - } - break; - - case ICMP_TIMESTAMP: - case ICMP_TIMESTAMPREPLY: - if (len < 20) - { - DEBUG_WRAP(DebugMessage(DEBUG_DECODE, - "Truncated ICMP header(%d bytes)\n", len);); - - DecoderEvent(p, DECODE_ICMP_DGRAM_LT_TIMESTAMPHDR); - - p->icmph = NULL; - dc.discards++; - dc.icmpdisc++; - - return; - } - break; - - case ICMP_ADDRESS: - case ICMP_ADDRESSREPLY: - if (len < 12) - { - DEBUG_WRAP(DebugMessage(DEBUG_DECODE, - "Truncated ICMP header(%d bytes)\n", len);); - - - DecoderEvent(p, DECODE_ICMP_DGRAM_LT_ADDRHDR); - - p->icmph = NULL; - dc.discards++; - dc.icmpdisc++; - - return; - } - break; - - default: - DecoderEvent(p, DECODE_ICMP4_TYPE_OTHER); - break; - } - - - if (ScIcmpChecksums()) - { - uint16_t csum = in_chksum_icmp((uint16_t *)p->icmph, len); - - if(csum) - { - p->error_flags |= PKT_ERR_CKSUM_ICMP; - DEBUG_WRAP(DebugMessage(DEBUG_DECODE, "Bad ICMP Checksum\n");); - execIcmpChksmDrop(p); - dc.invalid_checksums++; - } - else - { - DEBUG_WRAP(DebugMessage(DEBUG_DECODE,"ICMP Checksum: OK\n");); - } - } - - p->dsize = (u_short)(len - ICMP_HEADER_LEN); - p->data = pkt + ICMP_HEADER_LEN; - - DEBUG_WRAP(DebugMessage(DEBUG_DECODE, "ICMP type: %d code: %d\n", - p->icmph->type, p->icmph->code);); - - switch(p->icmph->type) - { - case ICMP_ECHO: - ICMP4AddrTests(p); - // fall through ... - - case ICMP_ECHOREPLY: - /* setup the pkt id and seq numbers */ - /* add the size of the echo ext to the data - * ptr and subtract it from the data size */ - p->dsize -= sizeof(ICMPHdr::icmp_hun.idseq); - p->data += sizeof(ICMPHdr::icmp_hun.idseq); - PushLayer(PROTO_ICMP4, p, pkt, ICMP_NORMAL_LEN); - break; - - case ICMP_DEST_UNREACH: - if ((p->icmph->code == ICMP_FRAG_NEEDED) - && (ntohs(p->icmph->s_icmp_nextmtu) < 576)) - { - DecoderEvent(p, DECODE_ICMP_PATH_MTU_DOS); - } - - /* Fall through */ - - case ICMP_SOURCE_QUENCH: - case ICMP_REDIRECT: - case ICMP_TIME_EXCEEDED: - case ICMP_PARAMETERPROB: - /* account for extra 4 bytes in header */ - p->dsize -= 4; - p->data += 4; - - PushLayer(PROTO_ICMP4, p, pkt, ICMP_NORMAL_LEN); - DecodeICMPEmbeddedIP(p->data, p->dsize, p); - break; - - default: - PushLayer(PROTO_ICMP4, p, pkt, ICMP_HEADER_LEN); - break; - } - - /* Run a bunch of ICMP decoder rules */ - ICMP4MiscTests(p); - - p->proto_bits |= PROTO_BIT__ICMP; - p->proto_bits &= ~(PROTO_BIT__UDP | PROTO_BIT__TCP); -} - -/* - * Function: DecodeICMPEmbeddedIP(uint8_t *, const uint32_t, Packet *) - * - * Purpose: Decode the ICMP embedded IP header + 64 bits payload - * - * 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 - */ -void DecodeICMPEmbeddedIP(const uint8_t *pkt, const uint32_t len, Packet *p) -{ - uint32_t ip_len; /* length from the start of the ip hdr to the - * pkt end */ - uint32_t hlen; /* ip header length */ - uint16_t orig_frag_offset; - - /* do a little validation */ - if(len < IP_HEADER_LEN) - { - DEBUG_WRAP(DebugMessage(DEBUG_DECODE, - "ICMP: IP short header (%d bytes)\n", len);); - - DecoderEvent(p, DECODE_ICMP_ORIG_IP_TRUNCATED); - - p->orig_family = NO_IP; - p->orig_iph = NULL; - return; - } - - /* lay the IP struct over the raw data */ - sfiph_orig_build(p, pkt, AF_INET); - p->orig_iph = (IPHdr *) pkt; - - DEBUG_WRAP(DebugMessage(DEBUG_DECODE, "DecodeICMPEmbeddedIP: ip header" - " starts at: %p, length is %lu\n", p->orig_iph, - (unsigned long) len);); - /* - * with datalink DLT_RAW it's impossible to differ ARP datagrams from IP. - * So we are just ignoring non IP datagrams - */ - if((GET_ORIG_IPH_VER(p) != 4) && !IS_IP6(p)) - { - DEBUG_WRAP(DebugMessage(DEBUG_DECODE, - "ICMP: not IPv4 datagram ([ver: 0x%x][len: 0x%x])\n", - GET_ORIG_IPH_VER(p), GET_ORIG_IPH_LEN(p));); - - DecoderEvent(p, DECODE_ICMP_ORIG_IP_VER_MISMATCH); - - p->orig_family = NO_IP; - p->orig_iph = NULL; - return; - } - - /* set the IP datagram length */ - ip_len = ntohs(GET_ORIG_IPH_LEN(p)); - - /* set the IP header length */ - hlen = (p->orig_ip4h->ip_verhl & 0x0f) << 2; - - if(len < hlen) - { - DEBUG_WRAP(DebugMessage(DEBUG_DECODE, - "ICMP: IP len (%d bytes) < IP hdr len (%d bytes), packet discarded\n", - ip_len, hlen);); - - DecoderEvent(p, DECODE_ICMP_ORIG_DGRAM_LT_ORIG_IP); - - p->orig_family = NO_IP; - p->orig_iph = NULL; - return; - } - - /* set the remaining packet length */ - ip_len = len - hlen; - - orig_frag_offset = ntohs(GET_ORIG_IPH_OFF(p)); - orig_frag_offset &= 0x1FFF; - - if (orig_frag_offset == 0) - { - /* Original IP payload should be 64 bits */ - if (ip_len < 8) - { - DecoderEvent(p, DECODE_ICMP_ORIG_PAYLOAD_LT_64); - - return; - } - /* ICMP error packets could contain as much of original payload - * as possible, but not exceed 576 bytes - */ - else if (ntohs(GET_IPH_LEN(p)) > 576) - { - DecoderEvent(p, DECODE_ICMP_ORIG_PAYLOAD_GT_576); - } - } - else - { - /* RFC states that only first frag will get an ICMP response */ - DecoderEvent(p, DECODE_ICMP_ORIG_IP_WITH_FRAGOFFSET); - return; - } - - DEBUG_WRAP(DebugMessage(DEBUG_DECODE, "ICMP Unreachable IP header length: " - "%lu\n", (unsigned long)hlen);); - - switch(GET_ORIG_IPH_PROTO(p)) - { - case IPPROTO_TCP: /* decode the interesting part of the header */ - p->orig_tcph = (TCPHdr *)(pkt + hlen); - - /* stuff more data into the printout data struct */ - p->orig_sp = ntohs(p->orig_tcph->th_sport); - p->orig_dp = ntohs(p->orig_tcph->th_dport); - - break; - - case IPPROTO_UDP: - p->orig_udph = (UDPHdr *)(pkt + hlen); - - /* fill in the printout data structs */ - p->orig_sp = ntohs(p->orig_udph->uh_sport); - p->orig_dp = ntohs(p->orig_udph->uh_dport); - - break; - - case IPPROTO_ICMP: - p->orig_icmph = (ICMPHdr *)(pkt + hlen); - break; - } - - return; -} - -/* - * Function: DecodeIPV6(uint8_t *, uint32_t) - * - * Purpose: Decoding IPv6 headers - * - * Arguments: pkt => ptr to the packet data - * len => length from here to the end of the packet - * - * Returns: void function - */ - -//-------------------------------------------------------------------- -// decode.c::IP6 misc -//-------------------------------------------------------------------- - -#define IP6_MULTICAST 0xFF // first/most significant octet -#define IP6_MULTICAST_SCOPE_RESERVED 0x00 -#define IP6_MULTICAST_SCOPE_INTERFACE 0x01 -#define IP6_MULTICAST_SCOPE_LINK 0x02 -#define IP6_MULTICAST_SCOPE_ADMIN 0x04 -#define IP6_MULTICAST_SCOPE_SITE 0x05 -#define IP6_MULTICAST_SCOPE_ORG 0x08 -#define IP6_MULTICAST_SCOPE_GLOBAL 0x0E - -/* Check for multiple IPv6 Multicast-related alerts */ -static void CheckIPV6Multicast(Packet *p) -{ - uint8_t multicast_scope; - - if ( p->ip6h->ip_src.ip.u6_addr8[0] == IP6_MULTICAST ) - { - DecoderEvent(p, DECODE_IPV6_SRC_MULTICAST); - } - if ( p->ip6h->ip_dst.ip.u6_addr8[0] != IP6_MULTICAST ) - { - return; - } - - multicast_scope = p->ip6h->ip_dst.ip.u6_addr8[1] & 0x0F; - switch (multicast_scope) - { - case IP6_MULTICAST_SCOPE_RESERVED: - case IP6_MULTICAST_SCOPE_INTERFACE: - case IP6_MULTICAST_SCOPE_LINK: - case IP6_MULTICAST_SCOPE_ADMIN: - case IP6_MULTICAST_SCOPE_SITE: - case IP6_MULTICAST_SCOPE_ORG: - case IP6_MULTICAST_SCOPE_GLOBAL: - break; - - default: - DecoderEvent(p, DECODE_IPV6_BAD_MULTICAST_SCOPE); - } - - /* Check against assigned multicast addresses. These are listed at: - http://www.iana.org/assignments/ipv6-multicast-addresses/ */ - - /* Multicast addresses only specify the first 16 and last 40 bits. - Others should be zero. */ - if ((p->ip6h->ip_dst.ip.u6_addr16[1] != 0) || - (p->ip6h->ip_dst.ip.u6_addr16[2] != 0) || - (p->ip6h->ip_dst.ip.u6_addr16[3] != 0) || - (p->ip6h->ip_dst.ip.u6_addr16[4] != 0) || - (p->ip6h->ip_dst.ip.u6_addr8[10] != 0)) - { - DecoderEvent(p, DECODE_IPV6_DST_RESERVED_MULTICAST); - return; - } - - if (p->ip6h->ip_dst.ip.u6_addr8[1] == IP6_MULTICAST_SCOPE_INTERFACE) - { - // Node-local scope - if ((p->ip6h->ip_dst.ip.u6_addr16[1] != 0) || - (p->ip6h->ip_dst.ip.u6_addr16[2] != 0) || - (p->ip6h->ip_dst.ip.u6_addr16[3] != 0) || - (p->ip6h->ip_dst.ip.u6_addr16[4] != 0) || - (p->ip6h->ip_dst.ip.u6_addr16[5] != 0) || - (p->ip6h->ip_dst.ip.u6_addr16[6] != 0)) - { - - DecoderEvent(p, DECODE_IPV6_DST_RESERVED_MULTICAST); - } - else - { - switch (ntohl(p->ip6h->ip_dst.ip.u6_addr32[3])) - { - case 0x00000001: // All Nodes - case 0x00000002: // All Routers - case 0x000000FB: // mDNSv6 - break; - default: - DecoderEvent(p, DECODE_IPV6_DST_RESERVED_MULTICAST); - } - } - } - else if (p->ip6h->ip_dst.ip.u6_addr8[1] == IP6_MULTICAST_SCOPE_LINK) - { - // Link-local scope - switch (ntohl(p->ip6h->ip_dst.ip.u6_addr32[3])) - { - case 0x00000001: // All Nodes - case 0x00000002: // All Routers - case 0x00000004: // DVMRP Routers - case 0x00000005: // OSPFIGP - case 0x00000006: // OSPFIGP Designated Routers - case 0x00000007: // ST Routers - case 0x00000008: // ST Hosts - case 0x00000009: // RIP Routers - case 0x0000000A: // EIGRP Routers - case 0x0000000B: // Mobile-Agents - case 0x0000000C: // SSDP - case 0x0000000D: // All PIMP Routers - case 0x0000000E: // RSVP-ENCAPSULATION - case 0x0000000F: // UPnP - case 0x00000012: // VRRP - case 0x00000016: // All MLDv2-capable routers - case 0x0000006A: // All-Snoopers - case 0x0000006B: // PTP-pdelay - case 0x0000006C: // Saratoga - case 0x0000006D: // LL-MANET-Routers - case 0x0000006E: // IGRS - case 0x0000006F: // iADT Discovery - case 0x000000FB: // mDNSv6 - case 0x00010001: // Link Name - case 0x00010002: // All-dhcp-agents - case 0x00010003: // Link-local Multicast Name Resolution - case 0x00010004: // DTCP Announcement - break; - default: - if ((p->ip6h->ip_dst.ip.u6_addr8[11] == 1) && - (p->ip6h->ip_dst.ip.u6_addr8[12] == 0xFF)) - { - break; // Solicited-Node Address - } - if ((p->ip6h->ip_dst.ip.u6_addr8[11] == 2) && - (p->ip6h->ip_dst.ip.u6_addr8[12] == 0xFF)) - { - break; // Node Information Queries - } - DecoderEvent(p, DECODE_IPV6_DST_RESERVED_MULTICAST); - } - } - else if (p->ip6h->ip_dst.ip.u6_addr8[1] == IP6_MULTICAST_SCOPE_SITE) - { - // Site-local scope - switch (ntohl(p->ip6h->ip_dst.ip.u6_addr32[3])) - { - case 0x00000002: // All Routers - case 0x000000FB: // mDNSv6 - case 0x00010003: // All-dhcp-servers - case 0x00010004: // Deprecated - case 0x00010005: // SL-MANET-ROUTERS - break; - default: - DecoderEvent(p, DECODE_IPV6_DST_RESERVED_MULTICAST); - } - } - else if ((p->ip6h->ip_dst.ip.u6_addr8[1] & 0xF0) == 0) - { - // Variable scope - switch (ntohl(p->ip6h->ip_dst.ip.u6_addr32[3])) - { - case 0x0000000C: // SSDP - case 0x000000FB: // mDNSv6 - case 0x00000181: // PTP-primary - case 0x00000182: // PTP-alternate1 - case 0x00000183: // PTP-alternate2 - case 0x00000184: // PTP-alternate3 - case 0x0000018C: // All ACs multicast address - case 0x00000201: // "rwho" Group (BSD) - case 0x00000202: // SUN RPC PMAPPROC_CALLIT - case 0x00000204: // All C1222 Nodes - case 0x00000300: // Mbus/IPv6 - case 0x00027FFE: // SAPv1 Announcements - case 0x00027FFF: // SAPv0 Announcements - break; - default: - if ((ntohl(p->ip6h->ip_dst.ip.u6_addr32[3]) >= 0x00000100) && - (ntohl(p->ip6h->ip_dst.ip.u6_addr32[3]) <= 0x00000136)) - { - break; // Several addresses assigned in a contiguous block - } - - if ((ntohl(p->ip6h->ip_dst.ip.u6_addr32[3]) >= 0x00000140) && - (ntohl(p->ip6h->ip_dst.ip.u6_addr32[3]) <= 0x0000014F)) - { - break; // EPSON-disc-set - } - - if ((ntohl(p->ip6h->ip_dst.ip.u6_addr32[3]) >= 0x00020000) && - (ntohl(p->ip6h->ip_dst.ip.u6_addr32[3]) <= 0x00027FFD)) - { - break; // Multimedia Conference Calls - } - - if ((ntohl(p->ip6h->ip_dst.ip.u6_addr32[3]) >= 0x00011000) && - (ntohl(p->ip6h->ip_dst.ip.u6_addr32[3]) <= 0x000113FF)) - { - break; // Service Location, Version 2 - } - - if ((ntohl(p->ip6h->ip_dst.ip.u6_addr32[3]) >= 0x00028000) && - (ntohl(p->ip6h->ip_dst.ip.u6_addr32[3]) <= 0x0002FFFF)) - { - break; // SAP Dynamic Assignments - } - - DecoderEvent(p, DECODE_IPV6_DST_RESERVED_MULTICAST); - } - } - else if ((p->ip6h->ip_dst.ip.u6_addr8[1] & 0xF0) == 0x30) - { - // Source-Specific Multicast block - if ((ntohl(p->ip6h->ip_dst.ip.u6_addr32[3]) >= 0x40000001) && - (ntohl(p->ip6h->ip_dst.ip.u6_addr32[3]) <= 0x7FFFFFFF)) - { - return; // IETF consensus - } - else if ((ntohl(p->ip6h->ip_dst.ip.u6_addr32[3]) >= 0x80000000) && - (ntohl(p->ip6h->ip_dst.ip.u6_addr32[3]) <= 0xFFFFFFFF)) - { - return; // Dynamiclly allocated by hosts when needed - } - else - { - // Other addresses in this block are reserved. - DecoderEvent(p, DECODE_IPV6_DST_RESERVED_MULTICAST); - } - } - else - { - /* Addresses not listed above are reserved. */ - DecoderEvent(p, DECODE_IPV6_DST_RESERVED_MULTICAST); - } -} - -/* Teredo packets need to have one of their IPs use either the Teredo prefix, - or a link-local prefix (in the case of Router Solicitation messages) */ -static inline int CheckTeredoPrefix(IP6RawHdr *hdr) -{ - /* Check if src address matches 2001::/32 */ - if ((hdr->ip6_src.s6_addr[0] == 0x20) && - (hdr->ip6_src.s6_addr[1] == 0x01) && - (hdr->ip6_src.s6_addr[2] == 0x00) && - (hdr->ip6_src.s6_addr[3] == 0x00)) - return 1; - - /* Check if src address matches fe80::/64 */ - if ((hdr->ip6_src.s6_addr[0] == 0xfe) && - (hdr->ip6_src.s6_addr[1] == 0x80) && - (hdr->ip6_src.s6_addr[2] == 0x00) && - (hdr->ip6_src.s6_addr[3] == 0x00) && - (hdr->ip6_src.s6_addr[4] == 0x00) && - (hdr->ip6_src.s6_addr[5] == 0x00) && - (hdr->ip6_src.s6_addr[6] == 0x00) && - (hdr->ip6_src.s6_addr[7] == 0x00)) - return 1; - - /* Check if dst address matches 2001::/32 */ - if ((hdr->ip6_dst.s6_addr[0] == 0x20) && - (hdr->ip6_dst.s6_addr[1] == 0x01) && - (hdr->ip6_dst.s6_addr[2] == 0x00) && - (hdr->ip6_dst.s6_addr[3] == 0x00)) - return 1; - - /* Check if dst address matches fe80::/64 */ - if ((hdr->ip6_dst.s6_addr[0] == 0xfe) && - (hdr->ip6_dst.s6_addr[1] == 0x80) && - (hdr->ip6_dst.s6_addr[2] == 0x00) && - (hdr->ip6_dst.s6_addr[3] == 0x00) && - (hdr->ip6_dst.s6_addr[4] == 0x00) && - (hdr->ip6_dst.s6_addr[5] == 0x00) && - (hdr->ip6_dst.s6_addr[6] == 0x00) && - (hdr->ip6_dst.s6_addr[7] == 0x00)) - return 1; - - /* No Teredo prefix found. */ - return 0; -} - -/* Function: IPV6MiscTests(Packet *p) - * - * Purpose: A bunch of IPv6 decoder alerts - * - * Arguments: p => the Packet to check - * - * Returns: void function - */ -static inline void IPV6MiscTests(Packet *p) -{ - /* - * Some IP Header tests - * Land Attack(same src/dst ip) - * Loopback (src or dst in 127/8 block) - * Modified: 2/22/05-man for High Endian Architecture. - * - * some points in the code assume an IP of 0.0.0.0 matches anything, but - * that is not so here. The sfip_compare makes that assumption for - * compatibility, but sfip_contains does not. Hence, sfip_contains - * is used here in the interrim. */ - if( sfip_contains(&p->ip6h->ip_src, &p->ip6h->ip_dst) == SFIP_CONTAINS) - { - DecoderEvent(p, DECODE_BAD_TRAFFIC_SAME_SRCDST); - } - - if(sfip_is_loopback(&p->ip6h->ip_src) || sfip_is_loopback(&p->ip6h->ip_dst)) - { - DecoderEvent(p, DECODE_BAD_TRAFFIC_LOOPBACK); - } - - /* Other decoder alerts for IPv6 addresses - Added: 5/24/10 (Snort 2.9.0) */ - if (!sfip_is_set(&p->ip6h->ip_dst)) - { - DecoderEvent(p, DECODE_IPV6_DST_ZERO); - } - - CheckIPV6Multicast(p); - - { - /* Only check for IPv6 over IPv4 */ - if (p->ip4h && p->ip4h->ip_proto == IPPROTO_IPV6) - { - uint32_t isatap_interface_id = ntohl(p->ip6h->ip_src.ip.u6_addr32[2]) & 0xFCFFFFFF; - - /* ISATAP uses address with prefix fe80:0000:0000:0000:0200:5efe or - fe80:0000:0000:0000:0000:5efe, followed by the IPv4 address. */ - if (isatap_interface_id == 0x00005EFE) - { - if (p->ip4h->ip_src.ip.u6_addr32[0] != p->ip6h->ip_src.ip.u6_addr32[3]) - DecoderEvent(p, DECODE_IPV6_ISATAP_SPOOF); - } - } - } -} - -//-------------------------------------------------------------------- -// decode.c::IP6 extensions -//-------------------------------------------------------------------- - -static inline int IPV6ExtensionOrder(uint8_t type) -{ - switch (type) - { - case IPPROTO_HOPOPTS: return 1; - case IPPROTO_DSTOPTS: return 2; - case IPPROTO_ROUTING: return 3; - case IPPROTO_FRAGMENT: return 4; - case IPPROTO_AH: return 5; - case IPPROTO_ESP: return 6; - default: return 7; - } -} - -/* Check for out-of-order IPv6 Extension Headers */ -static inline void CheckIPv6ExtensionOrder(Packet *p) -{ - int routing_seen = 0; - int current_type_order, next_type_order, i; - - { - if (p->ip6_extension_count > 0) - current_type_order = IPV6ExtensionOrder(p->ip6_extensions[0].type); - - for (i = 1; i < (p->ip6_extension_count); i++) - { - next_type_order = IPV6ExtensionOrder(p->ip6_extensions[i].type); - - if (p->ip6_extensions[i].type == IPPROTO_ROUTING) - routing_seen = 1; - - if (next_type_order <= current_type_order) - { - /* A second "Destination Options" header is allowed iff: - 1) A routing header was already seen, and - 2) The second destination header is the last one before the upper layer. - */ - if (!routing_seen || - !(p->ip6_extensions[i].type == IPPROTO_DSTOPTS) || - !(i+1 == p->ip6_extension_count)) - { - DecoderEvent(p, DECODE_IPV6_UNORDERED_EXTENSIONS); - } - } - - current_type_order = next_type_order; - } - } -} - -void DecodeIPV6Extensions(uint8_t next, const uint8_t *pkt, uint32_t len, Packet *p); - -static inline int CheckIPV6HopOptions(const uint8_t *pkt, uint32_t len, Packet *p) -{ - IP6Extension *exthdr = (IP6Extension *)pkt; - uint32_t total_octets = (exthdr->ip6e_len * 8) + 8; - const uint8_t *hdr_end = pkt + total_octets; - uint8_t type, oplen; - - if (len < total_octets) - DecoderEvent(p, DECODE_IPV6_TRUNCATED_EXT); - - /* Skip to the options */ - pkt += 2; - - /* Iterate through the options, check for bad ones */ - while (pkt < hdr_end) - { - type = *pkt; - switch (type) - { - case IP6_OPT_PAD1: - pkt++; - break; - case IP6_OPT_PADN: - case IP6_OPT_JUMBO: - case IP6_OPT_RTALERT: - case IP6_OPT_TUNNEL_ENCAP: - case IP6_OPT_QUICK_START: - case IP6_OPT_CALIPSO: - case IP6_OPT_HOME_ADDRESS: - case IP6_OPT_ENDPOINT_IDENT: - oplen = *(++pkt); - if ((pkt + oplen + 1) > hdr_end) - { - DecoderEvent(p, DECODE_IPV6_BAD_OPT_LEN); - return -1; - } - pkt += oplen + 1; - break; - default: - DecoderEvent(p, DECODE_IPV6_BAD_OPT_TYPE); - return -1; - } - } - - return 0; -} - -void DecodeIPV6Options(int type, const uint8_t *pkt, uint32_t len, Packet *p) -{ - IP6Extension *exthdr; - uint32_t hdrlen = 0; - - /* This should only be called by DecodeIPV6 or DecodeIPV6Extensions - * so no validation performed. Otherwise, uncomment the following: */ - /* if(IPH_IS_VALID(p)) return */ - - dc.ipv6opts++; - - /* Need at least two bytes, one for next header, one for len. */ - /* But size is an integer multiple of 8 octets, so 8 is min. */ - if(len < sizeof(IP6Extension)) - { - DecoderEvent(p, DECODE_IPV6_TRUNCATED_EXT); - return; - } - - if ( p->ip6_extension_count >= IP6_EXTMAX ) - { - DecoderEvent(p, DECODE_IP6_EXCESS_EXT_HDR); - return; - } - - exthdr = (IP6Extension *)pkt; - - p->ip6_extensions[p->ip6_extension_count].type = type; - p->ip6_extensions[p->ip6_extension_count].data = pkt; - - // TBD add layers for other ip6 ext headers - switch (type) - { - case IPPROTO_HOPOPTS: - if (len < sizeof(IP6HopByHop)) - { - DecoderEvent(p, DECODE_IPV6_TRUNCATED_EXT); - return; - } - hdrlen = sizeof(IP6Extension) + (exthdr->ip6e_len << 3); - - if ( CheckIPV6HopOptions(pkt, len, p) == 0 ) - PushLayer(PROTO_IP6_HOP_OPTS, p, pkt, hdrlen); - break; - - case IPPROTO_DSTOPTS: - if (len < sizeof(IP6Dest)) - { - DecoderEvent(p, DECODE_IPV6_TRUNCATED_EXT); - return; - } - if (exthdr->ip6e_nxt == IPPROTO_ROUTING) - { - DecoderEvent(p, DECODE_IPV6_DSTOPTS_WITH_ROUTING); - } - hdrlen = sizeof(IP6Extension) + (exthdr->ip6e_len << 3); - - if ( CheckIPV6HopOptions(pkt, len, p) == 0 ) - PushLayer(PROTO_IP6_DST_OPTS, p, pkt, hdrlen); - break; - - case IPPROTO_ROUTING: - if (len < sizeof(IP6Route)) - { - DecoderEvent(p, DECODE_IPV6_TRUNCATED_EXT); - return; - } - - /* Routing type 0 extension headers are evil creatures. */ - { - IP6Route *rte = (IP6Route *)exthdr; - - if (rte->ip6rte_type == 0) - { - DecoderEvent(p, DECODE_IPV6_ROUTE_ZERO); - } - } - - if (exthdr->ip6e_nxt == IPPROTO_HOPOPTS) - { - DecoderEvent(p, DECODE_IPV6_ROUTE_AND_HOPBYHOP); - } - if (exthdr->ip6e_nxt == IPPROTO_ROUTING) - { - DecoderEvent(p, DECODE_IPV6_TWO_ROUTE_HEADERS); - } - hdrlen = sizeof(IP6Extension) + (exthdr->ip6e_len << 3); - break; - - case IPPROTO_FRAGMENT: - if (len <= sizeof(IP6Frag)) - { - if ( len < sizeof(IP6Frag) ) - DecoderEvent(p, DECODE_IPV6_TRUNCATED_EXT); - else - DecoderEvent(p, DECODE_ZERO_LENGTH_FRAG); - return; - } - else - { - IP6Frag *ip6frag_hdr = (IP6Frag *)pkt; - /* If this is an IP Fragment, set some data... */ - p->ip6_frag_index = p->ip6_extension_count; - p->ip_frag_start = pkt + sizeof(IP6Frag); - - p->df = 0; - p->rf = IP6F_RES(ip6frag_hdr); - p->mf = IP6F_MF(ip6frag_hdr); - p->frag_offset = IP6F_OFFSET(ip6frag_hdr); - - if ( p->frag_offset || p->mf ) - { - p->frag_flag = 1; - dc.frag6++; - } - else - { - DecoderEvent(p, DECODE_IPV6_BAD_FRAG_PKT); - } - if ( !(p->frag_offset) ) - { - // check header ordering of fragged (next) header - if ( IPV6ExtensionOrder(ip6frag_hdr->ip6f_nxt) < - IPV6ExtensionOrder(IPPROTO_FRAGMENT) ) - DecoderEvent(p, DECODE_IPV6_UNORDERED_EXTENSIONS); - } - // check header ordering up thru frag header - CheckIPv6ExtensionOrder(p); - } - hdrlen = sizeof(IP6Frag); - p->ip_frag_len = (uint16_t)(len - hdrlen); - - if ( p->frag_flag && ((p->frag_offset > 0) || - (exthdr->ip6e_nxt != IPPROTO_UDP)) ) - { - /* For non-zero offset frags, we stop decoding after the - Frag header. According to RFC 2460, the "Next Header" - value may differ from that of the offset zero frag, - but only the Next Header of the original frag is used. */ - // check DecodeIP(); we handle frags the same way here - p->ip6_extension_count++; - return; - } - break; - - case IPPROTO_AH: - /* Auth Headers work in both IPv4 & IPv6, and their lengths are - given in 4-octet increments instead of 8-octet increments. */ - hdrlen = sizeof(IP6Extension) + (exthdr->ip6e_len << 2); - - if (hdrlen <= len) - PushLayer(PROTO_AH, p, pkt, hdrlen); - break; - - default: - hdrlen = sizeof(IP6Extension) + (exthdr->ip6e_len << 3); - break; - } - - p->ip6_extension_count++; - - if(hdrlen > len) - { - DecoderEvent(p, DECODE_IPV6_TRUNCATED_EXT); - return; - } - - if ( hdrlen > 0 ) - { - DecodeIPV6Extensions(*pkt, pkt + hdrlen, len - hdrlen, p); - } -#ifdef DEBUG_MSGS - else - { - DebugMessage(DEBUG_DECODE, "WARNING - no next ip6 header decoded\n"); - } -#endif -} - -void DecodeIPV6Extensions(uint8_t next, const uint8_t *pkt, uint32_t len, Packet *p) -{ - dc.ip6ext++; - - if (p->greh != NULL) - dc.gre_ipv6ext++; - - /* XXX might this introduce an issue if the "next" field is invalid? */ - p->ip6h->next = next; - - /* See if there are any ip_proto only rules that match */ - fpEvalIpProtoOnlyRules(snort_conf->ip_proto_only_lists, p); - p->proto_bits |= PROTO_BIT__IP; - - switch(next) { - case IPPROTO_TCP: - dc.tcp6++; - CheckIPv6ExtensionOrder(p); - DecodeTCP(pkt, len, p); - return; - case IPPROTO_UDP: - dc.udp6++; - CheckIPv6ExtensionOrder(p); - DecodeUDP(pkt, len, p); - return; - case IPPROTO_ICMPV6: - dc.icmp6++; - CheckIPv6ExtensionOrder(p); - DecodeICMP6(pkt , len, p); - return; - case IPPROTO_NONE: - CheckIPv6ExtensionOrder(p); - p->dsize = 0; - return; - case IPPROTO_HOPOPTS: - case IPPROTO_DSTOPTS: - case IPPROTO_ROUTING: - case IPPROTO_FRAGMENT: - case IPPROTO_AH: - DecodeIPV6Options(next, pkt, len, p); - // Anything special to do here? just return? - return; - case IPPROTO_GRE: - dc.gre++; - CheckIPv6ExtensionOrder(p); - DecodeGRE(pkt, len, p); - return; - case IPPROTO_IPIP: - dc.ip6ip4++; - if ( ScTunnelBypassEnabled(TUNNEL_4IN6) ) - Active_SetTunnelBypass(); - CheckIPv6ExtensionOrder(p); - DecodeIP(pkt, len, p); - return; - case IPPROTO_IPV6: - dc.ip6ip6++; - CheckIPv6ExtensionOrder(p); - DecodeIPV6(pkt, len, p); - return; - case IPPROTO_ESP: - CheckIPv6ExtensionOrder(p); - if (ScESPDecoding()) - DecodeESP(pkt, len, p); - return; - - default: - // There may be valid headers after this unsupported one, - // need to decode this header, set "next" and continue - // looping. - - DecoderEvent(p, DECODE_IPV6_BAD_NEXT_HEADER); - - dc.other++; - p->data = pkt; - p->dsize = (uint16_t)len; - break; - }; -} - -//-------------------------------------------------------------------- -// decode.c::IP6 decoder -//-------------------------------------------------------------------- - -void DecodeIPV6(const uint8_t *pkt, uint32_t len, Packet *p) -{ - IP6RawHdr *hdr; - uint32_t payload_len; - - dc.ipv6++; - - if (p->greh != NULL) - dc.gre_ipv6++; - - hdr = (IP6RawHdr*)pkt; - - if(len < IP6_HDR_LEN) - { - if ((p->packet_flags & PKT_UNSURE_ENCAP) == 0) - DecoderEvent(p, DECODE_IPV6_TRUNCATED); - - goto decodeipv6_fail; - } - - /* Verify version in IP6 Header agrees */ - if(IPRAW_HDR_VER(hdr) != 6) - { - if ((p->packet_flags & PKT_UNSURE_ENCAP) == 0) - DecoderEvent(p, DECODE_IPV6_IS_NOT); - - goto decodeipv6_fail; - } - - if (p->family != NO_IP) - { - /* Snort currently supports only 2 IP layers. Any more will fail to be - decoded. */ - if (p->encapsulated) - { - - DecoderAlertEncapsulated(p, DECODE_IP_MULTIPLE_ENCAPSULATION, pkt, len); - goto decodeipv6_fail; - } - else - { - p->encapsulated = 1; - p->outer_iph = p->iph; - p->outer_ip_data = p->ip_data; - p->outer_ip_dsize = p->ip_dsize; - } - } - payload_len = ntohs(hdr->ip6plen) + IP6_HDR_LEN; - - if(payload_len != len) - { - if (payload_len > len) - { - if ((p->packet_flags & PKT_UNSURE_ENCAP) == 0) - DecoderEvent(p, DECODE_IPV6_DGRAM_GT_CAPLEN); - - goto decodeipv6_fail; - } - } - - /* Teredo packets should always use the 2001:0000::/32 prefix, or in some - cases the link-local prefix fe80::/64. - Source: RFC 4380, section 2.6 & section 5.2.1 - - Checking the addresses will save us from numerous false positives - when UDP clients use 3544 as their ephemeral port, or "Deep Teredo - Inspection" is turned on. - - If we ever start decoding more than 2 layers of IP in a packet, this - check against p->proto_bits will need to be refactored. */ - if ((p->proto_bits & PROTO_BIT__TEREDO) && (CheckTeredoPrefix(hdr) == 0)) - { - goto decodeipv6_fail; - } - - /* lay the IP struct over the raw data */ - // this is ugly but necessary to keep the rest of the code happy - p->inner_iph = p->iph = (IPHdr *)pkt; - - /* Build Packet structure's version of the IP6 header */ - sfiph_build(p, hdr, AF_INET6); - - /* Remove outer IP options */ - if (p->encapsulated) - { - p->ip_options_data = NULL; - p->ip_options_len = 0; - } - p->ip_option_count = 0; - - /* set the real IP length for logging */ - p->actual_ip_len = ntohs(p->ip6h->len); - p->ip_data = pkt + IP6_HDR_LEN; - p->ip_dsize = ntohs(p->ip6h->len); - - PushLayer(PROTO_IP6, p, pkt, sizeof(*hdr)); - - IPV6MiscTests(p); - - DecodeIPV6Extensions(GET_IPH_PROTO(p), pkt + IP6_HDR_LEN, ntohs(p->ip6h->len), p); - return; - -decodeipv6_fail: - /* If this was Teredo, back up and treat the packet as normal UDP. */ - if (p->proto_bits & PROTO_BIT__TEREDO) - { - dc.ipv6--; - dc.teredo--; - p->proto_bits &= ~PROTO_BIT__TEREDO; - - if (p->greh != NULL) - dc.gre_ipv6--; - - if ( ScTunnelBypassEnabled(TUNNEL_TEREDO) ) - Active_ClearTunnelBypass(); - return; - } - - dc.discards++; - dc.ipv6disc++; -} - -//-------------------------------------------------------------------- -// decode.c::ICMP6 -//-------------------------------------------------------------------- - -void DecodeICMP6(const uint8_t *pkt, const uint32_t len, Packet *p) -{ - if(len < ICMP6_MIN_HEADER_LEN) - { - DEBUG_WRAP(DebugMessage(DEBUG_DECODE, - "WARNING: Truncated ICMP6 header (%d bytes).\n", len);); - - DecoderEvent(p, DECODE_ICMP6_HDR_TRUNC); - - dc.discards++; - return; - } - - p->icmp6h = (ICMP6Hdr*)pkt; - p->icmph = (ICMPHdr*)pkt; /* This is needed for icmp rules */ - - /* Do checksums */ - if (ScIcmpChecksums()) - { - uint16_t csum; - - if(IS_IP4(p)) - { - csum = in_chksum_icmp((uint16_t *)(p->icmp6h), len); - } - /* IPv6 traffic */ - else - { - pseudoheader6 ph6; - COPY4(ph6.sip, p->ip6h->ip_src.ip32); - COPY4(ph6.dip, p->ip6h->ip_dst.ip32); - ph6.zero = 0; - ph6.protocol = GET_IPH_PROTO(p); - ph6.len = htons((u_short)len); - - csum = in_chksum_icmp6(&ph6, (uint16_t *)(p->icmp6h), len); - } - if(csum) - { - p->error_flags |= PKT_ERR_CKSUM_ICMP; - DEBUG_WRAP(DebugMessage(DEBUG_DECODE, "Bad ICMP Checksum\n");); - execIcmpChksmDrop(p); - dc.invalid_checksums++; - } - else - { - DEBUG_WRAP(DebugMessage(DEBUG_DECODE,"ICMP Checksum: OK\n");); - } - } - - p->dsize = (u_short)(len - ICMP6_MIN_HEADER_LEN); - p->data = pkt + ICMP6_MIN_HEADER_LEN; - - DEBUG_WRAP(DebugMessage(DEBUG_DECODE, "ICMP type: %d code: %d\n", - p->icmp6h->type, p->icmp6h->code);); - - switch(p->icmp6h->type) - { - case ICMP6_ECHO: - case ICMP6_REPLY: - if (p->dsize >= sizeof(ICMPHdr::icmp_hun.idseq)) - { - /* Set data pointer to that of the "echo message" */ - /* add the size of the echo ext to the data - * ptr and subtract it from the data size */ - p->dsize -= sizeof(ICMPHdr::icmp_hun.idseq); - p->data += sizeof(ICMPHdr::icmp_hun.idseq); - - if ( p->ip6h->ip_dst.ip.u6_addr8[0] == IP6_MULTICAST ) - DecoderEvent(p, DECODE_ICMP6_DST_MULTICAST); - - PushLayer(PROTO_ICMP6, p, pkt, ICMP_NORMAL_LEN); - } - else - { - DEBUG_WRAP(DebugMessage(DEBUG_DECODE, - "WARNING: Truncated ICMP Echo header (%d bytes).\n", len);); - - DecoderEvent(p, DECODE_ICMP_DGRAM_LT_ICMPHDR); - - p->icmph = NULL; - p->icmp6h = NULL; - dc.discards++; - dc.icmpdisc++; - return; - } - break; - - case ICMP6_BIG: - if (p->dsize >= sizeof(ICMP6TooBig)) - { - ICMP6TooBig *too_big = (ICMP6TooBig *)pkt; - /* Set data pointer past MTU */ - p->data += 4; - p->dsize -= 4; - - if (ntohl(too_big->mtu) < 1280) - { - DecoderEvent(p, DECODE_ICMPV6_TOO_BIG_BAD_MTU); - } - - PushLayer(PROTO_ICMP6, p, pkt, ICMP_NORMAL_LEN); - DecodeICMPEmbeddedIP6(p->data, p->dsize, p); - } - else - { - DEBUG_WRAP(DebugMessage(DEBUG_DECODE, - "WARNING: Truncated ICMP header (%d bytes).\n", len);); - - DecoderEvent(p, DECODE_ICMP_DGRAM_LT_ICMPHDR); - - p->icmph = NULL; - p->icmp6h = NULL; - dc.discards++; - dc.icmpdisc++; - return; - } - break; - - case ICMP6_TIME: - case ICMP6_PARAMS: - case ICMP6_UNREACH: - if (p->dsize >= 4) - { - /* Set data pointer past the 'unused/mtu/pointer block */ - p->data += 4; - p->dsize -= 4; - - if (p->icmp6h->type == ICMP6_UNREACH) - { - if (p->icmp6h->code == 2) - { - DecoderEvent(p, DECODE_ICMPV6_UNREACHABLE_NON_RFC_2463_CODE); - } - else if (p->icmp6h->code > 6) - { - DecoderEvent(p, DECODE_ICMPV6_UNREACHABLE_NON_RFC_4443_CODE); - } - } - - PushLayer(PROTO_ICMP6, p, pkt, ICMP_NORMAL_LEN); - DecodeICMPEmbeddedIP6(p->data, p->dsize, p); - } - else - { - DEBUG_WRAP(DebugMessage(DEBUG_DECODE, - "WARNING: Truncated ICMP header (%d bytes).\n", len);); - - DecoderEvent(p, DECODE_ICMP_DGRAM_LT_ICMPHDR); - - p->icmph = NULL; - p->icmp6h = NULL; - dc.discards++; - dc.icmpdisc++; - return; - } - break; - - case ICMP6_ADVERTISEMENT: - if (p->dsize >= (sizeof(ICMP6RouterAdvertisement) - ICMP6_MIN_HEADER_LEN)) - { - ICMP6RouterAdvertisement *ra = (ICMP6RouterAdvertisement *)pkt; - if (p->icmp6h->code != 0) - { - DecoderEvent(p, DECODE_ICMPV6_ADVERT_BAD_CODE); - } - if (ntohl(ra->reachable_time) > 3600000) - { - DecoderEvent(p, DECODE_ICMPV6_ADVERT_BAD_REACHABLE); - } - PushLayer(PROTO_ICMP6, p, pkt, ICMP_HEADER_LEN); - } - else - { - DEBUG_WRAP(DebugMessage(DEBUG_DECODE, - "WARNING: Truncated ICMP header (%d bytes).\n", len);); - - DecoderEvent(p, DECODE_ICMP_DGRAM_LT_ICMPHDR); - - p->icmph = NULL; - p->icmp6h = NULL; - dc.discards++; - dc.icmpdisc++; - return; - } - break; - - case ICMP6_SOLICITATION: - if (p->dsize >= (sizeof(ICMP6RouterSolicitation) - ICMP6_MIN_HEADER_LEN)) - { - ICMP6RouterSolicitation *rs = (ICMP6RouterSolicitation *)pkt; - if (rs->code != 0) - { - DecoderEvent(p, DECODE_ICMPV6_SOLICITATION_BAD_CODE); - } - if (ntohl(rs->reserved) != 0) - { - DecoderEvent(p, DECODE_ICMPV6_SOLICITATION_BAD_RESERVED); - } - PushLayer(PROTO_ICMP6, p, pkt, ICMP_HEADER_LEN); - } - else - { - DEBUG_WRAP(DebugMessage(DEBUG_DECODE, - "WARNING: Truncated ICMP header (%d bytes).\n", len);); - - DecoderEvent(p, DECODE_ICMP_DGRAM_LT_ICMPHDR); - - p->icmph = NULL; - p->icmp6h = NULL; - dc.discards++; - dc.icmpdisc++; - return; - } - break; - - case ICMP6_NODE_INFO_QUERY: - case ICMP6_NODE_INFO_RESPONSE: - if (p->dsize >= (sizeof(ICMP6NodeInfo) - ICMP6_MIN_HEADER_LEN)) - { - ICMP6NodeInfo *ni = (ICMP6NodeInfo *)pkt; - if (ni->code > 2) - { - DecoderEvent(p, DECODE_ICMPV6_NODE_INFO_BAD_CODE); - } - /* TODO: Add alert for INFO Response, code == 1 || code == 2) - * and there is data. - */ - } - else - { - DEBUG_WRAP(DebugMessage(DEBUG_DECODE, - "WARNING: Truncated ICMP header (%d bytes).\n", len);); - - DecoderEvent(p, DECODE_ICMP_DGRAM_LT_ICMPHDR); - - p->icmph = NULL; - p->icmp6h = NULL; - dc.discards++; - dc.icmpdisc++; - return; - } - break; - - default: - DecoderEvent(p, DECODE_ICMP6_TYPE_OTHER); - - PushLayer(PROTO_ICMP6, p, pkt, ICMP_HEADER_LEN); - break; - } - - p->proto_bits |= PROTO_BIT__ICMP; - p->proto_bits &= ~(PROTO_BIT__UDP | PROTO_BIT__TCP); -} - -/* - * Function: DecodeICMPEmbeddedIP6(uint8_t *, const uint32_t, Packet *) - * - * Purpose: Decode the ICMP embedded IP6 header + payload - * - * 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 - */ -void DecodeICMPEmbeddedIP6(const uint8_t *pkt, const uint32_t len, Packet *p) -{ - uint16_t orig_frag_offset; - - /* lay the IP struct over the raw data */ - IP6RawHdr* hdr = (IP6RawHdr*)pkt; - dc.embdip++; - - DEBUG_WRAP(DebugMessage(DEBUG_DECODE, "DecodeICMPEmbeddedIP6: ip header" - " starts at: %p, length is %lu\n", hdr, - (unsigned long) len);); - - /* do a little validation */ - if ( len < IP6_HDR_LEN ) - { - DEBUG_WRAP(DebugMessage(DEBUG_DECODE, - "ICMP6: IP short header (%d bytes)\n", len);); - - DecoderEvent(p, DECODE_ICMP_ORIG_IP_TRUNCATED); - - dc.discards++; - return; - } - - /* - * with datalink DLT_RAW it's impossible to differ ARP datagrams from IP. - * So we are just ignoring non IP datagrams - */ - if(IPRAW_HDR_VER(hdr) != 6) - { - DEBUG_WRAP(DebugMessage(DEBUG_DECODE, - "ICMP: not IPv6 datagram ([ver: 0x%x][len: 0x%x])\n", - IPRAW_HDR_VER(hdr), len);); - - DecoderEvent(p, DECODE_ICMP_ORIG_IP_VER_MISMATCH); - - dc.discards++; - return; - } - - if ( len < IP6_HDR_LEN ) - { - DEBUG_WRAP(DebugMessage(DEBUG_DECODE, - "ICMP6: IP6 len (%d bytes) < IP6 hdr len (%d bytes), packet discarded\n", - len, IP6_HDR_LEN);); - - DecoderEvent(p, DECODE_ICMP_ORIG_DGRAM_LT_ORIG_IP); - - dc.discards++; - return; - } - sfiph_orig_build(p, pkt, AF_INET6); - - orig_frag_offset = ntohs(GET_ORIG_IPH_OFF(p)); - orig_frag_offset &= 0x1FFF; - - // XXX NOT YET IMPLEMENTED - fragments inside ICMP payload - - DEBUG_WRAP(DebugMessage(DEBUG_DECODE, "ICMP6 Unreachable IP6 header length: " - "%lu\n", (unsigned long)IP6_HDR_LEN);); - - switch(GET_ORIG_IPH_PROTO(p)) - { - case IPPROTO_TCP: /* decode the interesting part of the header */ - p->orig_tcph = (TCPHdr *)(pkt + IP6_HDR_LEN); - - /* stuff more data into the printout data struct */ - p->orig_sp = ntohs(p->orig_tcph->th_sport); - p->orig_dp = ntohs(p->orig_tcph->th_dport); - - break; - - case IPPROTO_UDP: - p->orig_udph = (UDPHdr *)(pkt + IP6_HDR_LEN); - - /* fill in the printout data structs */ - p->orig_sp = ntohs(p->orig_udph->uh_sport); - p->orig_dp = ntohs(p->orig_udph->uh_dport); - - break; - - case IPPROTO_ICMP: - p->orig_icmph = (ICMPHdr *)(pkt + IP6_HDR_LEN); - break; - } - - return; -} - -//-------------------------------------------------------------------- -// decode.c::Teredo -//-------------------------------------------------------------------- - -/* Function: DecodeTeredo(uint8_t *, uint32_t, Packet *) - * - * Teredo is IPv6 layered over UDP, with optional "indicators" in between. - * Decode these (if present) and go to DecodeIPv6. - * - */ - -void DecodeTeredo(const uint8_t *pkt, uint32_t len, Packet *p) -{ - if (len < TEREDO_MIN_LEN) - return; - - /* Decode indicators. If both are present, Auth always comes before Origin. */ - if (ntohs(*(uint16_t *)pkt) == TEREDO_INDICATOR_AUTH) - { - uint8_t client_id_length, auth_data_length; - - if (len < TEREDO_INDICATOR_AUTH_MIN_LEN) - return; - - client_id_length = *(pkt + 2); - auth_data_length = *(pkt + 3); - - if (len < (uint32_t)(TEREDO_INDICATOR_AUTH_MIN_LEN + client_id_length + auth_data_length)) - return; - - pkt += (TEREDO_INDICATOR_AUTH_MIN_LEN + client_id_length + auth_data_length); - len -= (TEREDO_INDICATOR_AUTH_MIN_LEN + client_id_length + auth_data_length); - } - - if (ntohs(*(uint16_t *)pkt) == TEREDO_INDICATOR_ORIGIN) - { - if (len < TEREDO_INDICATOR_ORIGIN_LEN) - return; - - pkt += TEREDO_INDICATOR_ORIGIN_LEN; - len -= TEREDO_INDICATOR_ORIGIN_LEN; - } - - /* If this is an IPv6 datagram, the first 4 bits will be the number 6. */ - if (( (*pkt & 0xF0) >> 4) == 6) - { - p->proto_bits |= PROTO_BIT__TEREDO; - dc.teredo++; - - if ( ScTunnelBypassEnabled(TUNNEL_TEREDO) ) - Active_SetTunnelBypass(); - - if (ScDeepTeredoInspection() && (p->sp != TEREDO_PORT) && (p->dp != TEREDO_PORT)) - p->packet_flags |= PKT_UNSURE_ENCAP; - - DecodeIPV6(pkt, len, p); - - p->packet_flags &= ~PKT_UNSURE_ENCAP; - } - - /* Otherwise, we treat this as normal UDP traffic. */ - return; -} - -//-------------------------------------------------------------------- -// decode.c::ESP -//-------------------------------------------------------------------- - -/* Function: DecodeAH - * - * Purpose: Decode Authentication Header - * - * NOTE: This is for IPv4 Auth Headers, we leave IPv6 to do its own - * work. - * - */ -void DecodeAH(const uint8_t *pkt, uint32_t len, Packet *p) -{ - IP6Extension *ah = (IP6Extension *)pkt; - uint8_t extlen = sizeof(*ah) + (ah->ip6e_len << 2); - - if (extlen > len) - { - return; - } - - PushLayer(PROTO_AH, p, pkt, extlen); - - DecodeIPv4Proto(ah->ip6e_nxt, pkt+extlen, len-extlen, p); -} - -/* - * Function: DecodeESP(const uint8_t *, uint32_t, Packet *) - * - * Purpose: Attempt to decode Encapsulated Security Payload. - * The contents are probably encrypted, but ESP is sometimes used - * with "null" encryption, solely for Authentication. - * This is more of a heuristic -- there is no ESP field that specifies - * the encryption type (or lack thereof). - * - * Arguments: pkt => ptr to the packet data - * len => length from here to the end of the packet - * p => ptr to the Packet struct being filled out - * - * Returns: void function - */ -void DecodeESP(const uint8_t *pkt, uint32_t len, Packet *p) -{ - const uint8_t *esp_payload; - uint8_t next_header; - uint8_t pad_length; - uint8_t save_layer = p->next_layer; - - /* The ESP header contains a crypto Initialization Vector (IV) and - a sequence number. Skip these. */ - if (len < (ESP_HEADER_LEN + ESP_AUTH_DATA_LEN + ESP_TRAILER_LEN)) - { - /* Truncated ESP traffic. Bail out here and inspect the rest as payload. */ - DecoderEvent(p, DECODE_ESP_HEADER_TRUNC); - p->data = pkt; - p->dsize = (uint16_t) len; - return; - } - esp_payload = pkt + ESP_HEADER_LEN; - - /* The Authentication Data at the end of the packet is variable-length. - RFC 2406 says that Encryption and Authentication algorithms MUST NOT - both be NULL, so we assume NULL Encryption and some other Authentication. - - The mandatory algorithms for Authentication are HMAC-MD5-96 and - HMAC-SHA-1-96, so we assume a 12-byte authentication data at the end. */ - len -= (ESP_HEADER_LEN + ESP_AUTH_DATA_LEN + ESP_TRAILER_LEN); - - pad_length = *(esp_payload + len); - next_header = *(esp_payload + len + 1); - - /* Adjust the packet length to account for the padding. - If the padding length is too big, this is probably encrypted traffic. */ - if (pad_length < len) - { - len -= (pad_length); - } - else - { - p->packet_flags |= PKT_TRUST; - p->data = esp_payload; - p->dsize = (u_short) len; - return; - } - - /* Attempt to decode the inner payload. - There is a small chance that an encrypted next_header would become a - different valid next_header. The PKT_UNSURE_ENCAP flag tells the next - decoder stage to silently ignore invalid headers. */ - - p->packet_flags |= PKT_UNSURE_ENCAP; - switch (next_header) - { - case IPPROTO_IPIP: - DecodeIP(esp_payload, len, p); - p->packet_flags &= ~PKT_UNSURE_ENCAP; - break; - - case IPPROTO_IPV6: - DecodeIPV6(esp_payload, len, p); - p->packet_flags &= ~PKT_UNSURE_ENCAP; - break; - - case IPPROTO_TCP: - dc.tcp++; - DecodeTCP(esp_payload, len, p); - p->packet_flags &= ~PKT_UNSURE_ENCAP; - break; - - case IPPROTO_UDP: - dc.udp++; - DecodeUDP(esp_payload, len, p); - p->packet_flags &= ~PKT_UNSURE_ENCAP; - break; - - case IPPROTO_ICMP: - dc.icmp++; - DecodeICMP(esp_payload, len, p); - p->packet_flags &= ~PKT_UNSURE_ENCAP; - break; - - case IPPROTO_GRE: - dc.gre++; - DecodeGRE(esp_payload, len, p); - p->packet_flags &= ~PKT_UNSURE_ENCAP; - break; - - default: - /* If we didn't get a valid next_header, this packet is probably - encrypted. Start data here and treat it as an IP datagram. */ - p->data = esp_payload; - p->dsize = (u_short) len; - p->packet_flags &= ~PKT_UNSURE_ENCAP; - p->packet_flags |= PKT_TRUST; - return; - } - - /* If no protocol was added to the stack, than we assume its' - * encrypted. */ - if (save_layer == p->next_layer) - p->packet_flags |= PKT_TRUST; -} - -//-------------------------------------------------------------------- -// decode.c::ERSPAN -//-------------------------------------------------------------------- - -/* - * Function: DecodeERSPANType2(uint8_t *, uint32_t, Packet *) - * - * Purpose: Decode Encapsulated Remote Switch Packet Analysis Type 2 - * This will decode ERSPAN Type 2 Headers - * - * Arguments: pkt => ptr to the packet data - * len => length from here to the end of the packet - * p => pointer to decoded packet struct - * - * Returns: void function - * - */ -void DecodeERSPANType2(const uint8_t *pkt, const uint32_t len, Packet *p) -{ - uint32_t hlen = sizeof(ERSpanType2Hdr); - uint32_t payload_len; - ERSpanType2Hdr *erSpan2Hdr = (ERSpanType2Hdr *)pkt; - - if (len < sizeof(ERSpanType2Hdr)) - { - DecoderAlertEncapsulated(p, DECODE_ERSPAN2_DGRAM_LT_HDR, pkt, len); - return; - } - - if (p->encapsulated) - { - /* discard packet - multiple encapsulation */ - /* not sure if this is ever used but I am assuming it is not */ - DecoderAlertEncapsulated(p, DECODE_IP_MULTIPLE_ENCAPSULATION, pkt, len); - return; - } - - /* Check that this is in fact ERSpan Type 2. - */ - if (ERSPAN_VERSION(erSpan2Hdr) != 0x01) /* Type 2 == version 0x01 */ - { - DecoderAlertEncapsulated(p, DECODE_ERSPAN_HDR_VERSION_MISMATCH, pkt, len); - return; - } - - PushLayer(PROTO_ERSPAN, p, pkt, hlen); - payload_len = len - hlen; - - DecodeTransBridging(pkt + hlen, payload_len, p); -} - -/* - * Function: DecodeERSPANType3(uint8_t *, uint32_t, Packet *) - * - * Purpose: Decode Encapsulated Remote Switch Packet Analysis Type 3 - * This will decode ERSPAN Type 3 Headers - * - * Arguments: pkt => ptr to the packet data - * len => length from here to the end of the packet - * p => pointer to decoded packet struct - * - * Returns: void function - * - */ -void DecodeERSPANType3(const uint8_t *pkt, const uint32_t len, Packet *p) -{ - uint32_t hlen = sizeof(ERSpanType3Hdr); - uint32_t payload_len; - ERSpanType3Hdr *erSpan3Hdr = (ERSpanType3Hdr *)pkt; - - if (len < sizeof(ERSpanType3Hdr)) - { - DecoderAlertEncapsulated(p, DECODE_ERSPAN3_DGRAM_LT_HDR, pkt, len); - return; - } - - if (p->encapsulated) - { - /* discard packet - multiple encapsulation */ - /* not sure if this is ever used but I am assuming it is not */ - DecoderAlertEncapsulated(p, DECODE_IP_MULTIPLE_ENCAPSULATION, pkt, len); - return; - } - - /* Check that this is in fact ERSpan Type 3. - */ - if (ERSPAN_VERSION(erSpan3Hdr) != 0x02) /* Type 3 == version 0x02 */ - { - DecoderAlertEncapsulated(p, DECODE_ERSPAN_HDR_VERSION_MISMATCH, pkt, len); - return; - } - - PushLayer(PROTO_ERSPAN, p, pkt, hlen); - payload_len = len - hlen; - - DecodeTransBridging(pkt + hlen, payload_len, p); -} - -//-------------------------------------------------------------------- -// decode.c::GRE -//-------------------------------------------------------------------- - -/* - * Function: DecodeGRE(uint8_t *, uint32_t, Packet *) - * - * Purpose: Decode Generic Routing Encapsulation Protocol - * This will decode normal GRE and PPTP GRE. - * - * Arguments: pkt => ptr to the packet data - * len => length from here to the end of the packet - * p => pointer to decoded packet struct - * - * Returns: void function - * - * Notes: see RFCs 1701, 2784 and 2637 - */ -void DecodeGRE(const uint8_t *pkt, const uint32_t len, Packet *p) -{ - uint32_t hlen; /* GRE header length */ - uint32_t payload_len; - - if (len < GRE_HEADER_LEN) - { - DecoderAlertEncapsulated(p, DECODE_GRE_DGRAM_LT_GREHDR, pkt, len); - return; - } - - if (p->encapsulated) - { - /* discard packet - multiple GRE encapsulation */ - /* not sure if this is ever used but I am assuming it is not */ - DecoderAlertEncapsulated(p, DECODE_IP_MULTIPLE_ENCAPSULATION, pkt, len); - return; - } - - /* Note: Since GRE doesn't have a field to indicate header length and - * can contain a few options, we need to walk through the header to - * figure out the length - */ - - p->greh = (GREHdr *)pkt; - hlen = GRE_HEADER_LEN; - - switch (GRE_VERSION(p->greh)) - { - case 0x00: - /* these must not be set */ - if (GRE_RECUR(p->greh) || GRE_FLAGS(p->greh)) - { - DecoderAlertEncapsulated(p, DECODE_GRE_INVALID_HEADER, pkt, len); - return; - } - - if (GRE_CHKSUM(p->greh) || GRE_ROUTE(p->greh)) - hlen += GRE_CHKSUM_LEN + GRE_OFFSET_LEN; - - if (GRE_KEY(p->greh)) - hlen += GRE_KEY_LEN; - - if (GRE_SEQ(p->greh)) - hlen += GRE_SEQ_LEN; - - /* if this flag is set, we need to walk through all of the - * Source Route Entries */ - if (GRE_ROUTE(p->greh)) - { - uint16_t sre_addrfamily; - uint8_t sre_offset; - uint8_t sre_length; - const uint8_t *sre_ptr; - - sre_ptr = pkt + hlen; - - while (1) - { - hlen += GRE_SRE_HEADER_LEN; - if (hlen > len) - break; - - sre_addrfamily = ntohs(*((uint16_t *)sre_ptr)); - sre_ptr += sizeof(sre_addrfamily); - - sre_offset = *((uint8_t *)sre_ptr); - sre_ptr += sizeof(sre_offset); - - sre_length = *((uint8_t *)sre_ptr); - sre_ptr += sizeof(sre_length); - - if ((sre_addrfamily == 0) && (sre_length == 0)) - break; - - hlen += sre_length; - sre_ptr += sre_length; - } - } - - break; - - /* PPTP */ - case 0x01: - /* these flags should never be present */ - if (GRE_CHKSUM(p->greh) || GRE_ROUTE(p->greh) || GRE_SSR(p->greh) || - GRE_RECUR(p->greh) || GRE_V1_FLAGS(p->greh)) - { - DecoderAlertEncapsulated(p, DECODE_GRE_V1_INVALID_HEADER, pkt, len); - return; - } - - /* protocol must be 0x880B - PPP */ - if (GRE_PROTO(p->greh) != GRE_TYPE_PPP) - { - DecoderAlertEncapsulated(p, DECODE_GRE_V1_INVALID_HEADER, pkt, len); - return; - } - - /* this flag should always be present */ - if (!(GRE_KEY(p->greh))) - { - DecoderAlertEncapsulated(p, DECODE_GRE_V1_INVALID_HEADER, pkt, len); - return; - } - - hlen += GRE_KEY_LEN; - - if (GRE_SEQ(p->greh)) - hlen += GRE_SEQ_LEN; - - if (GRE_V1_ACK(p->greh)) - hlen += GRE_V1_ACK_LEN; - - break; - - default: - DecoderAlertEncapsulated(p, DECODE_GRE_INVALID_VERSION, pkt, len); - return; - } - - if (hlen > len) - { - DecoderAlertEncapsulated(p, DECODE_GRE_DGRAM_LT_GREHDR, pkt, len); - return; - } - - PushLayer(PROTO_GRE, p, pkt, hlen); - payload_len = len - hlen; - - /* Send to next protocol decoder */ - /* As described in RFC 2784 the possible protocols are listed in - * RFC 1700 under "ETHER TYPES" - * See also "Current List of Protocol Types" in RFC 1701 - */ - switch (GRE_PROTO(p->greh)) - { - case ETHERNET_TYPE_IP: - DecodeIP(pkt + hlen, payload_len, p); - return; - - case GRE_TYPE_TRANS_BRIDGING: - DecodeTransBridging(pkt + hlen, payload_len, p); - return; - - case ETHERNET_TYPE_ARP: - case ETHERNET_TYPE_REVARP: - /* clear outer IP headers */ - p->iph = NULL; - p->family = NO_IP; - DecodeARP(pkt + hlen, payload_len, p); - return; - - case ETHERNET_TYPE_IPV6: - DecodeIPV6(pkt + hlen, payload_len, p); - return; - - case GRE_TYPE_PPP: - DecodePppPktEncapsulated(pkt + hlen, payload_len, p); - return; - - case ETHERNET_TYPE_ERSPAN_TYPE2: - DecodeERSPANType2(pkt + hlen, payload_len, p); - return; - - case ETHERNET_TYPE_ERSPAN_TYPE3: - DecodeERSPANType3(pkt + hlen, payload_len, p); - return; - -#ifndef NO_NON_ETHER_DECODER - case ETHERNET_TYPE_IPX: - DecodeIPX(pkt + hlen, payload_len, p); - return; -#endif - - case ETHERNET_TYPE_LOOP: - DecodeEthLoopback(pkt + hlen, payload_len, p); - return; - - /* not sure if this occurs, but 802.1q is an Ether type */ - case ETHERNET_TYPE_8021Q: - DecodeVlan(pkt + hlen, payload_len, p); - return; - - default: - // TBD add decoder drop event for unknown gre/eth type - dc.other++; - p->data = pkt + hlen; - p->dsize = (uint16_t)payload_len; - return; - } -} - -//-------------------------------------------------------------------- -// decode.c::GTP -//-------------------------------------------------------------------- - -/* Function: DecodeGTP(uint8_t *, uint32_t, Packet *) - * - * GTP (GPRS Tunneling Protocol) is layered over UDP. - * Decode these (if present) and go to DecodeIPv6/DecodeIP. - * - */ - -void DecodeGTP(const uint8_t *pkt, uint32_t len, Packet *p) -{ - uint32_t header_len; - uint8_t next_hdr_type; - uint8_t version; - uint8_t ip_ver; - GTPHdr *hdr; - - DEBUG_WRAP(DebugMessage(DEBUG_DECODE, "Start GTP decoding.\n");); - - hdr = (GTPHdr *) pkt; - - if (p->GTPencapsulated) - { - DecoderAlertEncapsulated(p, DECODE_GTP_MULTIPLE_ENCAPSULATION, pkt, len); - return; - } - else - { - p->GTPencapsulated = 1; - } - /*Check the length*/ - if (len < GTP_MIN_LEN) - return; - /* We only care about PDU*/ - if ( hdr->type != 255) - return; - /*Check whether this is GTP or GTP', Exit if GTP'*/ - if (!(hdr->flag & 0x10)) - return; - - /*The first 3 bits are version number*/ - version = (hdr->flag & 0xE0) >> 5; - switch (version) - { - case 0: /*GTP v0*/ - DEBUG_WRAP(DebugMessage(DEBUG_DECODE, "GTP v0 packets.\n");); - - header_len = GTP_V0_HEADER_LEN; - /*Check header fields*/ - if (len < header_len) - { - DecoderEvent(p, DECODE_GTP_BAD_LEN); - return; - } - - p->proto_bits |= PROTO_BIT__GTP; - - /*Check the length field. */ - if (len != ((unsigned int)ntohs(hdr->length) + header_len)) - { - DEBUG_WRAP(DebugMessage(DEBUG_DECODE, "Calculated length %d != %d in header.\n", - len - header_len, ntohs(hdr->length));); - DecoderEvent(p, DECODE_GTP_BAD_LEN); - return; - } - - break; - case 1: /*GTP v1*/ - DEBUG_WRAP(DebugMessage(DEBUG_DECODE, "GTP v1 packets.\n");); - - /*Check the length based on optional fields and extension header*/ - if (hdr->flag & 0x07) - { - - header_len = GTP_V1_HEADER_LEN; - - /*Check optional fields*/ - if (len < header_len) - { - DecoderEvent(p, DECODE_GTP_BAD_LEN); - return; - } - next_hdr_type = *(pkt + header_len - 1); - - /*Check extension headers*/ - while (next_hdr_type) - { - uint16_t ext_hdr_len; - /*check length before reading data*/ - if (len < header_len + 4) - { - DecoderEvent(p, DECODE_GTP_BAD_LEN); - return; - } - - ext_hdr_len = *(pkt + header_len); - - if (!ext_hdr_len) - { - DecoderEvent(p, DECODE_GTP_BAD_LEN); - return; - } - /*Extension header length is a unit of 4 octets*/ - header_len += ext_hdr_len * 4; - - /*check length before reading data*/ - if (len < header_len) - { - DecoderEvent(p, DECODE_GTP_BAD_LEN); - return; - } - next_hdr_type = *(pkt + header_len - 1); - } - } - else - header_len = GTP_MIN_LEN; - - p->proto_bits |= PROTO_BIT__GTP; - - /*Check the length field. */ - if (len != ((unsigned int)ntohs(hdr->length) + GTP_MIN_LEN)) - { - DEBUG_WRAP(DebugMessage(DEBUG_DECODE, "Calculated length %d != %d in header.\n", - len - GTP_MIN_LEN, ntohs(hdr->length));); - DecoderEvent(p, DECODE_GTP_BAD_LEN); - return; - } - - break; - default: - DEBUG_WRAP(DebugMessage(DEBUG_DECODE, "Unknown protocol version.\n");); - return; - - } - - PushLayer(PROTO_GTP, p, pkt, header_len); - - if ( ScTunnelBypassEnabled(TUNNEL_GTP) ) - Active_SetTunnelBypass(); - - len -= header_len; - if (len > 0) - { - ip_ver = *(pkt+header_len) & 0xF0; - if (ip_ver == 0x40) - DecodeIP(pkt+header_len, len, p); - else if (ip_ver == 0x60) - DecodeIPV6(pkt+header_len, len, p); - p->packet_flags &= ~PKT_UNSURE_ENCAP; - } - -} - -//-------------------------------------------------------------------- -// decode.c::UDP -//-------------------------------------------------------------------- - -/* UDP-layer decoder alerts */ -static inline void UDPMiscTests(Packet *p) -{ - { - if (p->dsize > 4000) - DecoderEvent(p, DECODE_UDP_LARGE_PACKET); - } - - { - if (p->sp == 0 || p->dp == 0) - DecoderEvent(p, DECODE_UDP_PORT_ZERO); - } -} - -/* - * Function: DecodeUDP(uint8_t *, const uint32_t, Packet *) - * - * Purpose: Decode the UDP transport layer - * - * Arguments: pkt => ptr to the packet data - * len => length from here to the end of the packet - * p => pointer to decoded packet struct - * - * Returns: void function - */ -static inline void PopUdp (Packet* p) -{ - p->udph = p->outer_udph; - p->outer_udph = NULL; - dc.discards++; - dc.udisc++; - - // required for detect.c to short-circuit preprocessing - if ( !p->dsize ) - p->dsize = p->ip_dsize; -} - -void DecodeUDP(const uint8_t * pkt, const uint32_t len, Packet * p) -{ - uint16_t uhlen; - u_char fragmented_udp_flag = 0; - - if (p->proto_bits & (PROTO_BIT__TEREDO | PROTO_BIT__GTP)) - p->outer_udph = p->udph; - - if(len < sizeof(UDPHdr)) - { - DEBUG_WRAP(DebugMessage(DEBUG_DECODE, - "Truncated UDP header (%d bytes)\n", len);); - - DecoderEvent(p, DECODE_UDP_DGRAM_LT_UDPHDR); - - PopUdp(p); - return; - } - - /* set the ptr to the start of the UDP header */ - p->inner_udph = p->udph = (UDPHdr *) pkt; - - if (!p->frag_flag) - { - uhlen = ntohs(p->udph->uh_len); - } - else - { - if(IS_IP6(p)) - { - uint16_t ip_len = ntohs(GET_IPH_LEN(p)); - /* subtract the distance from udp header to 1st ip6 extension */ - /* This gives the length of the UDP "payload", when fragmented */ - uhlen = ip_len - ((u_char *)p->udph - (u_char *)p->ip6_extensions[0].data); - } - else - { - uint16_t ip_len = ntohs(GET_IPH_LEN(p)); - /* Don't forget, IP_HLEN is a word - multiply x 4 */ - uhlen = ip_len - (GET_IPH_HLEN(p) * 4 ); - } - fragmented_udp_flag = 1; - } - - /* verify that the header len is a valid value */ - if(uhlen < UDP_HEADER_LEN) - { - DecoderEvent(p, DECODE_UDP_DGRAM_INVALID_LENGTH); - - PopUdp(p); - return; - } - - /* make sure there are enough bytes as designated by length field */ - if(uhlen > len) - { - DecoderEvent(p, DECODE_UDP_DGRAM_SHORT_PACKET); - - PopUdp(p); - return; - } - else if(uhlen < len) - { - DecoderEvent(p, DECODE_UDP_DGRAM_LONG_PACKET); - - PopUdp(p); - return; - } - - if (ScUdpChecksums()) - { - /* look at the UDP checksum to make sure we've got a good packet */ - uint16_t csum; - if(IS_IP4(p)) - { - pseudoheader ph; - ph.sip = *p->ip4h->ip_src.ip32; - ph.dip = *p->ip4h->ip_dst.ip32; - ph.zero = 0; - ph.protocol = GET_IPH_PROTO(p); - ph.len = p->udph->uh_len; - /* Don't do checksum calculation if - * 1) Fragmented, OR - * 2) UDP header chksum value is 0. - */ - if( !fragmented_udp_flag && p->udph->uh_chk ) - { - csum = in_chksum_udp(&ph, - (uint16_t *)(p->udph), uhlen); - } - else - { - csum = 0; - } - } - else - { - pseudoheader6 ph6; - COPY4(ph6.sip, p->ip6h->ip_src.ip32); - COPY4(ph6.dip, p->ip6h->ip_dst.ip32); - ph6.zero = 0; - ph6.protocol = GET_IPH_PROTO(p); - ph6.len = htons((u_short)len); - - /* Alert on checksum value 0 for ipv6 packets */ - if(!p->udph->uh_chk) - { - csum = 1; - DecoderEvent(p, DECODE_UDP_IPV6_ZERO_CHECKSUM); - } - /* Don't do checksum calculation if - * 1) Fragmented - * (UDP checksum is not optional in IP6) - */ - else if( !fragmented_udp_flag ) - { - csum = in_chksum_udp6(&ph6, - (uint16_t *)(p->udph), uhlen); - } - else - { - csum = 0; - } - } - if(csum) - { - /* Don't drop the packet if this was ESP or Teredo. - Just stop decoding. */ - if (p->packet_flags & PKT_UNSURE_ENCAP) - { - PopUdp(p); - return; - } - - p->error_flags |= PKT_ERR_CKSUM_UDP; - DEBUG_WRAP(DebugMessage(DEBUG_DECODE, "Bad UDP Checksum\n");); - execUdpChksmDrop(p); - dc.invalid_checksums++; - } - else - { - DEBUG_WRAP(DebugMessage(DEBUG_DECODE, "UDP Checksum: OK\n");); - } - } - - /* fill in the printout data structs */ - p->sp = ntohs(p->udph->uh_sport); - p->dp = ntohs(p->udph->uh_dport); - - DEBUG_WRAP(DebugMessage(DEBUG_DECODE, "UDP header starts at: %p\n", p->udph);); - - PushLayer(PROTO_UDP, p, pkt, sizeof(*p->udph)); - - p->data = (uint8_t *) (pkt + UDP_HEADER_LEN); - - /* length was validated up above */ - p->dsize = uhlen - UDP_HEADER_LEN; - - p->proto_bits |= PROTO_BIT__UDP; - - /* Drop packet if we ignore this port */ - if (ScIgnoreUdpPort(p->sp) || ScIgnoreUdpPort(p->dp)) - { - /* Ignore all preprocessors for this packet */ - p->packet_flags |= PKT_IGNORE; - return; - } - - UDPMiscTests(p); - - if (p->sp == TEREDO_PORT || - p->dp == TEREDO_PORT || - ScDeepTeredoInspection()) - { - if ( !p->frag_flag ) - DecodeTeredo(pkt + sizeof(UDPHdr), len - sizeof(UDPHdr), p); - } - if (ScGTPDecoding() && - (ScIsGTPPort(p->sp)||ScIsGTPPort(p->dp))) - { - if ( !p->frag_flag ) - DecodeGTP(pkt + sizeof(UDPHdr), len - sizeof(UDPHdr), p); - } - -} - -//-------------------------------------------------------------------- -// decode.c::TCP -//-------------------------------------------------------------------- - -/* TCP-layer decoder alerts */ -static inline void TCPMiscTests(Packet *p) -{ - { - if ( ((p->tcph->th_flags & TH_NORESERVED) == TH_SYN ) && - (p->tcph->th_seq == htonl(674711609)) ) - DecoderEvent(p, DECODE_TCP_SHAFT_SYNFLOOD); - } - - { - if (p->sp == 0 || p->dp == 0) - DecoderEvent(p, DECODE_TCP_PORT_ZERO); - } -} - -/* - * Function: DecodeTCP(uint8_t *, const uint32_t, Packet *) - * - * Purpose: Decode the TCP transport layer - * - * Arguments: pkt => ptr to the packet data - * len => length from here to the end of the packet - * p => Pointer to packet decode struct - * - * Returns: void function - */ -void DecodeTCP(const uint8_t * pkt, const uint32_t len, Packet * p) -{ - uint32_t hlen; /* TCP header length */ - - if(len < TCP_HEADER_LEN) - { - DEBUG_WRAP(DebugMessage(DEBUG_DECODE, - "TCP packet (len = %d) cannot contain " "20 byte header\n", len);); - - DecoderEvent(p, DECODE_TCP_DGRAM_LT_TCPHDR); - - p->tcph = NULL; - dc.discards++; - dc.tdisc++; - - return; - } - - /* lay TCP on top of the data cause there is enough of it! */ - p->tcph = (TCPHdr *) pkt; - - /* multiply the payload offset value by 4 */ - hlen = TCP_OFFSET(p->tcph) << 2; - - DEBUG_WRAP(DebugMessage(DEBUG_DECODE, "TCP th_off is %d, passed len is %lu\n", - TCP_OFFSET(p->tcph), (unsigned long)len);); - - if(hlen < TCP_HEADER_LEN) - { - DEBUG_WRAP(DebugMessage(DEBUG_DECODE, - "TCP Data Offset (%d) < hlen (%d) \n", - TCP_OFFSET(p->tcph), hlen);); - - DecoderEvent(p, DECODE_TCP_INVALID_OFFSET); - - p->tcph = NULL; - dc.discards++; - dc.tdisc++; - - return; - } - - if(hlen > len) - { - DEBUG_WRAP(DebugMessage(DEBUG_DECODE, - "TCP Data Offset(%d) < longer than payload(%d)!\n", - TCP_OFFSET(p->tcph) << 2, len);); - - DecoderEvent(p, DECODE_TCP_LARGE_OFFSET); - - p->tcph = NULL; - dc.discards++; - dc.tdisc++; - - return; - } - - /* Checksum code moved in front of the other decoder alerts. - If it's a bad checksum (maybe due to encrypted ESP traffic), the other - alerts could be false positives. */ - if (ScTcpChecksums()) - { - uint16_t csum; - if(IS_IP4(p)) - { - pseudoheader ph; - ph.sip = *p->ip4h->ip_src.ip32; - ph.dip = *p->ip4h->ip_dst.ip32; - /* setup the pseudo header for checksum calculation */ - ph.zero = 0; - ph.protocol = GET_IPH_PROTO(p); - ph.len = htons((u_short)len); - - /* if we're being "stateless" we probably don't care about the TCP - * checksum, but it's not bad to keep around for shits and giggles */ - /* calculate the checksum */ - csum = in_chksum_tcp(&ph, (uint16_t *)(p->tcph), len); - } - /* IPv6 traffic */ - else - { - pseudoheader6 ph6; - COPY4(ph6.sip, p->ip6h->ip_src.ip32); - COPY4(ph6.dip, p->ip6h->ip_dst.ip32); - ph6.zero = 0; - ph6.protocol = GET_IPH_PROTO(p); - ph6.len = htons((u_short)len); - - csum = in_chksum_tcp6(&ph6, (uint16_t *)(p->tcph), len); - } - - if(csum) - { - /* Don't drop the packet if this is encapuslated in Teredo or ESP. - Just get rid of the TCP header and stop decoding. */ - if (p->packet_flags & PKT_UNSURE_ENCAP) - { - p->tcph = NULL; - return; - } - - p->error_flags |= PKT_ERR_CKSUM_TCP; - DEBUG_WRAP(DebugMessage(DEBUG_DECODE, "Bad TCP checksum\n", - "0x%x versus 0x%x\n", csum, - ntohs(p->tcph->th_sum));); - - execTcpChksmDrop(p); - dc.invalid_checksums++; - } - else - { - DEBUG_WRAP(DebugMessage(DEBUG_DECODE,"TCP Checksum: OK\n");); - } - } - - { - if(TCP_ISFLAGSET(p->tcph, (TH_FIN|TH_PUSH|TH_URG))) - { - if(TCP_ISFLAGSET(p->tcph, (TH_SYN|TH_ACK|TH_RST))) - { - DecoderEvent(p, DECODE_TCP_XMAS); - } - else - { - DecoderEvent(p, DECODE_TCP_NMAP_XMAS); - } - // Allowing this packet for further processing - // (in case there is a valid data inside it). - /*p->tcph = NULL; - dc.discards++; - dc.tdisc++; - return;*/ - } - } - - if(TCP_ISFLAGSET(p->tcph, (TH_SYN))) - { - /* check if only SYN is set */ - if( p->tcph->th_flags == TH_SYN ) - { - { - if( p->tcph->th_seq == 6060842 ) - { - if( GET_IPH_ID(p) == 413 ) - { - DecoderEvent(p, DECODE_DOS_NAPTHA); - } - } - } - } - - { - if( IpAddrSetContains(SynToMulticastDstIp, GET_DST_ADDR(p)) ) - { - DecoderEvent(p, DECODE_SYN_TO_MULTICAST); - } - } - if ( (p->tcph->th_flags & TH_RST) ) - DecoderEvent(p, DECODE_TCP_SYN_RST); - - if ( (p->tcph->th_flags & TH_FIN) ) - DecoderEvent(p, DECODE_TCP_SYN_FIN); - } - else - { // we already know there is no SYN - if ( !(p->tcph->th_flags & (TH_ACK|TH_RST)) ) - DecoderEvent(p, DECODE_TCP_NO_SYN_ACK_RST); - } - - if ( (p->tcph->th_flags & (TH_FIN|TH_PUSH|TH_URG)) && - !(p->tcph->th_flags & TH_ACK) ) - DecoderEvent(p, DECODE_TCP_MUST_ACK); - - /* stuff more data into the printout data struct */ - p->sp = ntohs(p->tcph->th_sport); - p->dp = ntohs(p->tcph->th_dport); - - - DEBUG_WRAP(DebugMessage(DEBUG_DECODE, "tcp header starts at: %p\n", p->tcph);); - - PushLayer(PROTO_TCP, p, pkt, hlen); - - /* if options are present, decode them */ - p->tcp_options_len = (uint16_t)(hlen - TCP_HEADER_LEN); - - if(p->tcp_options_len > 0) - { - DEBUG_WRAP(DebugMessage(DEBUG_DECODE, "%lu bytes of tcp options....\n", - (unsigned long)(p->tcp_options_len));); - - p->tcp_options_data = pkt + TCP_HEADER_LEN; - DecodeTCPOptions((uint8_t *) (pkt + TCP_HEADER_LEN), p->tcp_options_len, p); - } - else - { - p->tcp_option_count = 0; - } - - /* set the data pointer and size */ - p->data = (uint8_t *) (pkt + hlen); - - if(hlen < len) - { - p->dsize = (u_short)(len - hlen); - } - else - { - p->dsize = 0; - } - - if ( (p->tcph->th_flags & TH_URG) && - (!p->dsize || ntohs(p->tcph->th_urp) > p->dsize) ) - DecoderEvent(p, DECODE_TCP_BAD_URP); - - p->proto_bits |= PROTO_BIT__TCP; - - /* Drop packet if we ignore this port */ - if (ScIgnoreTcpPort(p->sp) || ScIgnoreTcpPort(p->dp)) - { - /* Ignore all preprocessors for this packet */ - p->packet_flags |= PKT_IGNORE; - return; - } - - TCPMiscTests(p); -} - -//-------------------------------------------------------------------- -// decode.c::Option Handling -//-------------------------------------------------------------------- - -/** - * Validate that the length is an expected length AND that it's in bounds - * - * EOL and NOP are handled separately - * - * @param option_ptr current location - * @param end the byte past the end of the decode list - * @param len_ptr the pointer to the length field - * @param expected_len the number of bytes we expect to see per rfc KIND+LEN+DATA, -1 means dynamic. - * @param tcpopt options structure to populate - * @param byte_skip distance to move upon completion - * - * @return returns 0 on success, < 0 on error - */ -static inline int OptLenValidate(const uint8_t *option_ptr, - const uint8_t *end, - const uint8_t *len_ptr, - int expected_len, - Options *tcpopt, - uint8_t *byte_skip) -{ - *byte_skip = 0; - - if(len_ptr == NULL) - { - return TCP_OPT_TRUNC; - } - - if(*len_ptr == 0 || expected_len == 0 || expected_len == 1) - { - return TCP_OPT_BADLEN; - } - else if(expected_len > 1) - { - if((option_ptr + expected_len) > end) - { - /* not enough data to read in a perfect world */ - return TCP_OPT_TRUNC; - } - - if(*len_ptr != expected_len) - { - /* length is not valid */ - return TCP_OPT_BADLEN; - } - } - else /* expected_len < 0 (i.e. variable length) */ - { - if(*len_ptr < 2) - { - /* RFC sez that we MUST have atleast this much data */ - return TCP_OPT_BADLEN; - } - - if((option_ptr + *len_ptr) > end) - { - /* not enough data to read in a perfect world */ - return TCP_OPT_TRUNC; - } - } - - tcpopt->len = *len_ptr - 2; - - if(*len_ptr == 2) - { - tcpopt->data = NULL; - } - else - { - tcpopt->data = option_ptr + 2; - } - - *byte_skip = *len_ptr; - - return 0; -} - -/* - * Function: DecodeTCPOptions(uint8_t *, uint32_t, Packet *) - * - * Purpose: Fairly self explainatory name, don't you think? - * - * TCP Option Header length validation is left to the caller - * - * For a good listing of TCP Options, - * http://www.iana.org/assignments/tcp-parameters - * - * ------------------------------------------------------------ - * From: "Kastenholz, Frank" - * Subject: Re: skeeter & bubba TCP options? - * - * ah, the sins of ones youth that never seem to be lost... - * - * it was something that ben levy and stev and i did at ftp many - * many moons ago. bridgham and stev were the instigators of it. - * the idea was simple, put a dh key exchange directly in tcp - * so that all tcp sessions could be encrypted without requiring - * any significant key management system. authentication was not - * a part of the idea, it was to be provided by passwords or - * whatever, which could now be transmitted over the internet - * with impunity since they were encrypted... we implemented - * a simple form of this (doing the math was non trivial on the - * machines of the day). it worked. the only failure that i - * remember was that it was vulnerable to man-in-the-middle - * attacks. - * - * why "skeeter" and "bubba"? well, that's known only to stev... - * ------------------------------------------------------------ - * - * 4.2.2.5 TCP Options: RFC-793 Section 3.1 - * - * A TCP MUST be able to receive a TCP option in any segment. A TCP - * MUST ignore without error any TCP option it does not implement, - * assuming that the option has a length field (all TCP options - * defined in the future will have length fields). TCP MUST be - * prepared to handle an illegal option length (e.g., zero) without - * crashing; a suggested procedure is to reset the connection and log - * the reason. - * - * Arguments: o_list => ptr to the option list - * o_len => length of the option list - * p => pointer to decoded packet struct - * - * Returns: void function - */ -void DecodeTCPOptions(const uint8_t *start, uint32_t o_len, Packet *p) -{ - const uint8_t *option_ptr = start; - const uint8_t *end_ptr = start + o_len; /* points to byte after last option */ - const uint8_t *len_ptr; - uint8_t opt_count = 0; - u_char done = 0; /* have we reached TCPOPT_EOL yet?*/ - u_char experimental_option_found = 0; /* are all options RFC compliant? */ - u_char obsolete_option_found = 0; - u_char ttcp_found = 0; - - int code = 2; - uint8_t byte_skip; - - /* Here's what we're doing so that when we find out what these - * other buggers of TCP option codes are, we can do something - * useful - * - * 1) get option code - * 2) check for enough space for current option code - * 3) set option data ptr - * 4) increment option code ptr - * - * TCP_OPTLENMAX = 40 because of - * (((2^4) - 1) * 4 - TCP_HEADER_LEN) - * - */ - - if(o_len > TCP_OPTLENMAX) - { - /* This shouldn't ever alert if we are doing our job properly - * in the caller */ - p->tcph = NULL; /* let's just alert */ - DEBUG_WRAP(DebugMessage(DEBUG_DECODE, - "o_len(%u) > TCP_OPTLENMAX(%u)\n", - o_len, TCP_OPTLENMAX)); - return; - } - - while((option_ptr < end_ptr) && (opt_count < TCP_OPTLENMAX) && (code >= 0) && !done) - { - p->tcp_options[opt_count].code = *option_ptr; - - if((option_ptr + 1) < end_ptr) - { - len_ptr = option_ptr + 1; - } - else - { - len_ptr = NULL; - } - - switch(*option_ptr) - { - case TCPOPT_EOL: - done = 1; /* fall through to the NOP case */ - case TCPOPT_NOP: - p->tcp_options[opt_count].len = 0; - p->tcp_options[opt_count].data = NULL; - byte_skip = 1; - code = 0; - break; - case TCPOPT_MAXSEG: - code = OptLenValidate(option_ptr, end_ptr, len_ptr, TCPOLEN_MAXSEG, - &p->tcp_options[opt_count], &byte_skip); - break; - case TCPOPT_SACKOK: - code = OptLenValidate(option_ptr, end_ptr, len_ptr, TCPOLEN_SACKOK, - &p->tcp_options[opt_count], &byte_skip); - break; - case TCPOPT_WSCALE: - code = OptLenValidate(option_ptr, end_ptr, len_ptr, TCPOLEN_WSCALE, - &p->tcp_options[opt_count], &byte_skip); - if (code == 0) - { - if ( - ((uint16_t) p->tcp_options[opt_count].data[0] > 14)) - { - /* LOG INVALID WINDOWSCALE alert */ - DecoderEvent(p, DECODE_TCPOPT_WSCALE_INVALID); - } - } - break; - case TCPOPT_ECHO: /* both use the same lengths */ - case TCPOPT_ECHOREPLY: - obsolete_option_found = 1; - code = OptLenValidate(option_ptr, end_ptr, len_ptr, TCPOLEN_ECHO, - &p->tcp_options[opt_count], &byte_skip); - break; - case TCPOPT_MD5SIG: - /* RFC 5925 obsoletes this option (see below) */ - obsolete_option_found = 1; - code = OptLenValidate(option_ptr, end_ptr, len_ptr, TCPOLEN_MD5SIG, - &p->tcp_options[opt_count], &byte_skip); - break; - case TCPOPT_AUTH: - /* Has to have at least 4 bytes - see RFC 5925, Section 2.2 */ - if ((len_ptr != NULL) && (*len_ptr < 4)) - code = TCP_OPT_BADLEN; - else - code = OptLenValidate(option_ptr, end_ptr, len_ptr, -1, - &p->tcp_options[opt_count], &byte_skip); - break; - case TCPOPT_SACK: - code = OptLenValidate(option_ptr, end_ptr, len_ptr, -1, - &p->tcp_options[opt_count], &byte_skip); - if((code == 0) && (p->tcp_options[opt_count].data == NULL)) - code = TCP_OPT_BADLEN; - - break; - case TCPOPT_CC_ECHO: - ttcp_found = 1; - /* fall through */ - case TCPOPT_CC: /* all 3 use the same lengths / T/TCP */ - case TCPOPT_CC_NEW: - code = OptLenValidate(option_ptr, end_ptr, len_ptr, TCPOLEN_CC, - &p->tcp_options[opt_count], &byte_skip); - break; - case TCPOPT_TRAILER_CSUM: - experimental_option_found = 1; - code = OptLenValidate(option_ptr, end_ptr, len_ptr, TCPOLEN_TRAILER_CSUM, - &p->tcp_options[opt_count], &byte_skip); - break; - - case TCPOPT_TIMESTAMP: - code = OptLenValidate(option_ptr, end_ptr, len_ptr, TCPOLEN_TIMESTAMP, - &p->tcp_options[opt_count], &byte_skip); - break; - - case TCPOPT_SKEETER: - case TCPOPT_BUBBA: - case TCPOPT_UNASSIGNED: - obsolete_option_found = 1; - code = OptLenValidate(option_ptr, end_ptr, len_ptr, -1, - &p->tcp_options[opt_count], &byte_skip); - break; - default: - case TCPOPT_SCPS: - case TCPOPT_SELNEGACK: - case TCPOPT_RECORDBOUND: - case TCPOPT_CORRUPTION: - case TCPOPT_PARTIAL_PERM: - case TCPOPT_PARTIAL_SVC: - case TCPOPT_ALTCSUM: - case TCPOPT_SNAP: - experimental_option_found = 1; - code = OptLenValidate(option_ptr, end_ptr, len_ptr, -1, - &p->tcp_options[opt_count], &byte_skip); - break; - } - - if(code < 0) - { - if(code == TCP_OPT_BADLEN) - { - DecoderEvent(p, DECODE_TCPOPT_BADLEN); - } - else if(code == TCP_OPT_TRUNC) - { - DecoderEvent(p, DECODE_TCPOPT_TRUNCATED); - } - - /* set the option count to the number of valid - * options found before this bad one - * some implementations (BSD and Linux) ignore - * the bad ones, but accept the good ones */ - p->tcp_option_count = opt_count; - - return; - } - - opt_count++; - - option_ptr += byte_skip; - } - - p->tcp_option_count = opt_count; - - if (experimental_option_found) - { - DecoderEvent(p, DECODE_TCPOPT_EXPERIMENTAL); - } - else if (obsolete_option_found) - { - DecoderEvent(p, DECODE_TCPOPT_OBSOLETE); - } - else if (ttcp_found) - { - DecoderEvent(p, DECODE_TCPOPT_TTCP); - } - - return; -} - - -/* - * Function: DecodeIPOptions(uint8_t *, uint32_t, Packet *) - * - * Purpose: Once again, a fairly self-explainatory name - * - * Arguments: o_list => ptr to the option list - * o_len => length of the option list - * p => pointer to decoded packet struct - * - * Returns: void function - */ -void DecodeIPOptions(const uint8_t *start, uint32_t o_len, Packet *p) -{ - const uint8_t *option_ptr = start; - u_char done = 0; /* have we reached IP_OPTEOL yet? */ - const uint8_t *end_ptr = start + o_len; - uint8_t opt_count = 0; /* what option are we processing right now */ - uint8_t byte_skip; - const uint8_t *len_ptr; - int code = 0; /* negative error codes are returned from bad options */ - - - DEBUG_WRAP(DebugMessage(DEBUG_DECODE, "Decoding %d bytes of IP options\n", o_len);); - - - while((option_ptr < end_ptr) && (opt_count < IP_OPTMAX) && (code >= 0)) - { - p->ip_options[opt_count].code = *option_ptr; - - if((option_ptr + 1) < end_ptr) - { - len_ptr = option_ptr + 1; - } - else - { - len_ptr = NULL; - } - - switch(*option_ptr) - { - case IPOPT_NOP: - case IPOPT_EOL: - /* if we hit an EOL, we're done */ - if(*option_ptr == IPOPT_EOL) - done = 1; - - p->ip_options[opt_count].len = 0; - p->ip_options[opt_count].data = NULL; - byte_skip = 1; - break; - default: - /* handle all the dynamic features */ - code = OptLenValidate(option_ptr, end_ptr, len_ptr, -1, - &p->ip_options[opt_count], &byte_skip); - } - - if(code < 0) - { - /* Yes, we use TCP_OPT_* for the IP option decoder. - */ - if(code == TCP_OPT_BADLEN) - { - DecoderEvent(p, DECODE_IPV4OPT_BADLEN); - } - else if(code == TCP_OPT_TRUNC) - { - DecoderEvent(p, DECODE_IPV4OPT_TRUNCATED); - } - return; - } - - if(!done) - opt_count++; - - option_ptr += byte_skip; - } - - p->ip_option_count = opt_count; - - return; -} - -//-------------------------------------------------------------------- -// decode.c::NON-ETHER STUFF -//-------------------------------------------------------------------- - -#ifndef NO_NON_ETHER_DECODER -#ifdef DLT_IEEE802_11 -/* - * Function: DecodeIEEE80211Pkt(Packet *, char *, DAQ_PktHdr_t*, - * uint8_t*) - * - * Purpose: Decode those fun loving wireless LAN 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 DecodeIEEE80211Pkt(Packet * p, const DAQ_PktHdr_t * pkthdr, - const uint8_t * pkt) -{ - uint32_t cap_len = pkthdr->caplen; - PROFILE_VARS; - - PREPROC_PROFILE_START(decodePerfStats); - - dc.total_processed++; - - memset(p, 0, PKT_ZERO_LEN); - - p->pkth = pkthdr; - p->pkt = pkt; - - DEBUG_WRAP(DebugMessage(DEBUG_DECODE, "Packet!\n");); - DEBUG_WRAP(DebugMessage(DEBUG_DECODE, "caplen: %lu pktlen: %lu\n", - (unsigned long)cap_len, (unsigned long)pkthdr->pktlen);); - - /* do a little validation */ - if(cap_len < MINIMAL_IEEE80211_HEADER_LEN) - { - if (ScLogVerbose()) - { - ErrorMessage("Captured data length < IEEE 802.11 header length! " - "(%d bytes)\n", cap_len); - } - - PREPROC_PROFILE_END(decodePerfStats); - return; - } - /* lay the wireless structure over the packet data */ - p->wifih = (WifiHdr *) pkt; - - DEBUG_WRAP(DebugMessage(DEBUG_DECODE, "%X %X\n", *p->wifih->addr1, - *p->wifih->addr2);); - - /* determine frame type */ - switch(p->wifih->frame_control & 0x00ff) - { - /* management frames */ - case WLAN_TYPE_MGMT_ASREQ: - case WLAN_TYPE_MGMT_ASRES: - case WLAN_TYPE_MGMT_REREQ: - case WLAN_TYPE_MGMT_RERES: - case WLAN_TYPE_MGMT_PRREQ: - case WLAN_TYPE_MGMT_PRRES: - case WLAN_TYPE_MGMT_BEACON: - case WLAN_TYPE_MGMT_ATIM: - case WLAN_TYPE_MGMT_DIS: - case WLAN_TYPE_MGMT_AUTH: - case WLAN_TYPE_MGMT_DEAUTH: - dc.wifi_mgmt++; - break; - - /* Control frames */ - case WLAN_TYPE_CONT_PS: - case WLAN_TYPE_CONT_RTS: - case WLAN_TYPE_CONT_CTS: - case WLAN_TYPE_CONT_ACK: - case WLAN_TYPE_CONT_CFE: - case WLAN_TYPE_CONT_CFACK: - dc.wifi_control++; - break; - /* Data packets without data */ - case WLAN_TYPE_DATA_NULL: - case WLAN_TYPE_DATA_CFACK: - case WLAN_TYPE_DATA_CFPL: - case WLAN_TYPE_DATA_ACKPL: - - dc.wifi_data++; - break; - case WLAN_TYPE_DATA_DTCFACK: - case WLAN_TYPE_DATA_DTCFPL: - case WLAN_TYPE_DATA_DTACKPL: - case WLAN_TYPE_DATA_DATA: - dc.wifi_data++; - - if(cap_len < IEEE802_11_DATA_HDR_LEN + sizeof(EthLlc)) - { - DecoderEvent(p, DECODE_BAD_80211_ETHLLC); - - PREPROC_PROFILE_END(decodePerfStats); - return; - } - - p->ehllc = (EthLlc *) (pkt + IEEE802_11_DATA_HDR_LEN); - -#ifdef DEBUG_MSGS - LogNetData((uint8_t*) p->ehllc, sizeof(EthLlc), NULL); - - printf("LLC Header:\n"); - printf(" DSAP: 0x%X\n", p->ehllc->dsap); - printf(" SSAP: 0x%X\n", p->ehllc->ssap); -#endif - - if(p->ehllc->dsap == ETH_DSAP_IP && p->ehllc->ssap == ETH_SSAP_IP) - { - if(cap_len < IEEE802_11_DATA_HDR_LEN + - sizeof(EthLlc) + sizeof(EthLlcOther)) - { - DecoderEvent(p, DECODE_BAD_80211_OTHER); - - PREPROC_PROFILE_END(decodePerfStats); - return; - } - - p->ehllcother = (EthLlcOther *) (pkt + IEEE802_11_DATA_HDR_LEN + sizeof(EthLlc)); -#ifdef DEBUG_MSGS - LogNetData((uint8_t*)p->ehllcother, sizeof(EthLlcOther), NULL); - - printf("LLC Other Header:\n"); - printf(" CTRL: 0x%X\n", p->ehllcother->ctrl); - printf(" ORG: 0x%02X%02X%02X\n", p->ehllcother->org_code[0], - p->ehllcother->org_code[1], p->ehllcother->org_code[2]); - printf(" PROTO: 0x%04X\n", ntohs(p->ehllcother->proto_id)); -#endif - - switch(ntohs(p->ehllcother->proto_id)) - { - case ETHERNET_TYPE_IP: - DecodeIP(p->pkt + IEEE802_11_DATA_HDR_LEN + sizeof(EthLlc) + - sizeof(EthLlcOther), - cap_len - IEEE802_11_DATA_HDR_LEN - sizeof(EthLlc) - - sizeof(EthLlcOther), p); - PREPROC_PROFILE_END(decodePerfStats); - return; - - case ETHERNET_TYPE_ARP: - case ETHERNET_TYPE_REVARP: - DecodeARP(p->pkt + IEEE802_11_DATA_HDR_LEN + sizeof(EthLlc) + - sizeof(EthLlcOther), - cap_len - IEEE802_11_DATA_HDR_LEN - sizeof(EthLlc) - - sizeof(EthLlcOther), p); - PREPROC_PROFILE_END(decodePerfStats); - return; - case ETHERNET_TYPE_EAPOL: - DecodeEapol(p->pkt + IEEE802_11_DATA_HDR_LEN + sizeof(EthLlc) + - sizeof(EthLlcOther), - cap_len - IEEE802_11_DATA_HDR_LEN - sizeof(EthLlc) - - sizeof(EthLlcOther), p); - PREPROC_PROFILE_END(decodePerfStats); - return; - case ETHERNET_TYPE_8021Q: - DecodeVlan(p->pkt + IEEE802_11_DATA_HDR_LEN , - cap_len - IEEE802_11_DATA_HDR_LEN , p); - PREPROC_PROFILE_END(decodePerfStats); - return; - - case ETHERNET_TYPE_IPV6: - DecodeIPV6(p->pkt + IEEE802_11_DATA_HDR_LEN, - cap_len - IEEE802_11_DATA_HDR_LEN, p); - PREPROC_PROFILE_END(decodePerfStats); - return; - - default: - // TBD add decoder drop event for unknown wifi/eth type - dc.other++; - PREPROC_PROFILE_END(decodePerfStats); - return; - } - } - break; - default: - // TBD add decoder drop event for unknown wlan frame type - dc.other++; - break; - } - - PREPROC_PROFILE_END(decodePerfStats); - return; -} -#endif // DLT_IEEE802_11 - -/* - * Function: DecodeTRPkt(Packet *, char *, DAQ_PktHdr_t*, uint8_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, const DAQ_PktHdr_t * pkthdr, const uint8_t * pkt) -{ - uint32_t cap_len = pkthdr->caplen; - uint32_t dataoff; /* data offset is variable here */ - PROFILE_VARS; - - PREPROC_PROFILE_START(decodePerfStats); - - dc.total_processed++; - - memset(p, 0, PKT_ZERO_LEN); - - p->pkth = pkthdr; - p->pkt = pkt; - - DEBUG_WRAP(DebugMessage(DEBUG_DECODE, "Packet!\n"); - DebugMessage(DEBUG_DECODE, "caplen: %lu pktlen: %lu\n", - (unsigned long)cap_len,(unsigned long) pkthdr->pktlen); - ); - - if(cap_len < sizeof(Trh_hdr)) - { - DEBUG_WRAP(DebugMessage(DEBUG_DECODE, - "Captured data length < Token Ring header length! " - "(%d < %d bytes)\n", cap_len, TR_HLEN);); - - DecoderEvent(p, DECODE_BAD_TRH); - - PREPROC_PROFILE_END(decodePerfStats); - 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 - */ - if(cap_len < (sizeof(Trh_hdr) + sizeof(Trh_llc))) - { - DEBUG_WRAP(DebugMessage(DEBUG_DECODE, - "Captured data length < Token Ring header length! " - "(%d < %d bytes)\n", cap_len, - (sizeof(Trh_hdr) + sizeof(Trh_llc)));); - - DecoderEvent(p, DECODE_BAD_TR_ETHLLC); - - PREPROC_PROFILE_END(decodePerfStats); - return; - } - - - 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 ... - */ - - if(cap_len < (sizeof(Trh_hdr) + sizeof(Trh_llc) + sizeof(Trh_mr))) - { - DEBUG_WRAP(DebugMessage(DEBUG_DECODE, - "Captured data length < Token Ring header length! " - "(%d < %d bytes)\n", cap_len, - (sizeof(Trh_hdr) + sizeof(Trh_llc) + sizeof(Trh_mr)));); - - DecoderEvent(p, DECODE_BAD_TRHMR); - - PREPROC_PROFILE_END(decodePerfStats); - return; - } - - p->trhmr = (Trh_mr *) (pkt + sizeof(Trh_hdr)); - - - if(cap_len < (sizeof(Trh_hdr) + sizeof(Trh_llc) + - sizeof(Trh_mr) + TRH_MR_LEN(p->trhmr))) - { - DEBUG_WRAP(DebugMessage(DEBUG_DECODE, - "Captured data length < Token Ring header length! " - "(%d < %d bytes)\n", cap_len, - (sizeof(Trh_hdr) + sizeof(Trh_llc) + sizeof(Trh_mr)));); - - DecoderEvent(p, DECODE_BAD_TR_MR_LEN); - - PREPROC_PROFILE_END(decodePerfStats); - return; - } - - p->trhllc = (Trh_llc *) (pkt + sizeof(Trh_hdr) + TRH_MR_LEN(p->trhmr)); - dataoff = sizeof(Trh_hdr) + TRH_MR_LEN(p->trhmr) + 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) - { - DEBUG_WRAP( - DebugMessage(DEBUG_DECODE, "DSAP and SSAP arent set to SNAP\n"); - ); - p->trhllc = NULL; - PREPROC_PROFILE_END(decodePerfStats); - return; - } - - switch(htons(p->trhllc->ethertype)) - { - case ETHERNET_TYPE_IP: - DEBUG_WRAP(DebugMessage(DEBUG_DECODE, "Decoding IP\n");); - DecodeIP(p->pkt + dataoff, cap_len - dataoff, p); - PREPROC_PROFILE_END(decodePerfStats); - return; - - case ETHERNET_TYPE_ARP: - case ETHERNET_TYPE_REVARP: - DEBUG_WRAP( - DebugMessage(DEBUG_DECODE, "Decoding ARP\n"); - ); - dc.arp++; - - PREPROC_PROFILE_END(decodePerfStats); - return; - - case ETHERNET_TYPE_8021Q: - DecodeVlan(p->pkt + dataoff, cap_len - dataoff, p); - PREPROC_PROFILE_END(decodePerfStats); - return; - - default: - DEBUG_WRAP(DebugMessage(DEBUG_DECODE, "Unknown network protocol: %d\n", - htons(p->trhllc->ethertype))); - // TBD add decoder drop event for unknown tr/eth type - dc.other++; - PREPROC_PROFILE_END(decodePerfStats); - return; - } - - PREPROC_PROFILE_END(decodePerfStats); - return; -} - - -/* - * Function: DecodeFDDIPkt(Packet *, char *, DAQ_PktHdr_t*, uint8_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, const DAQ_PktHdr_t * pkthdr, const uint8_t * pkt) -{ - uint32_t cap_len = pkthdr->caplen; - uint32_t dataoff = sizeof(Fddi_hdr) + sizeof(Fddi_llc_saps); - PROFILE_VARS; - - PREPROC_PROFILE_START(decodePerfStats); - - dc.total_processed++; - - memset(p, 0, PKT_ZERO_LEN); - - p->pkth = pkthdr; - p->pkt = pkt; - - DEBUG_WRAP(DebugMessage(DEBUG_DECODE,"Packet!\n"); - DebugMessage(DEBUG_DECODE, "caplen: %lu pktlen: %lu\n", - (unsigned long) cap_len,(unsigned long) pkthdr->pktlen); - ); - - /* Bounds checking (might not be right yet -worm5er) */ - if(cap_len < dataoff) - { - if (ScLogVerbose()) - { - ErrorMessage("Captured data length < FDDI header length! " - "(%d %d bytes)\n", cap_len, dataoff); - PREPROC_PROFILE_END(decodePerfStats); - 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)) - { - dataoff += sizeof(Fddi_llc_iparp); - - if(cap_len < dataoff) - { - if (ScLogVerbose()) - { - ErrorMessage("Captured data length < FDDI header length! " - "(%d %d bytes)\n", cap_len, dataoff); - PREPROC_PROFILE_END(decodePerfStats); - return; - } - } - - p->fddiiparp = (Fddi_llc_iparp *) (pkt + sizeof(Fddi_hdr) + sizeof(Fddi_llc_saps)); - } - else if((p->fddisaps->dsap == FDDI_DSAP_SNA) && - (p->fddisaps->ssap == FDDI_SSAP_SNA)) - { - dataoff += sizeof(Fddi_llc_sna); - - if(cap_len < dataoff) - { - if (ScLogVerbose()) - { - ErrorMessage("Captured data length < FDDI header length! " - "(%d %d bytes)\n", cap_len, dataoff); - PREPROC_PROFILE_END(decodePerfStats); - return; - } - } - - p->fddisna = (Fddi_llc_sna *) (pkt + sizeof(Fddi_hdr) + - sizeof(Fddi_llc_saps)); - } - else - { - dataoff += sizeof(Fddi_llc_other); - p->fddiother = (Fddi_llc_other *) (pkt + sizeof(Fddi_hdr) + - sizeof(Fddi_llc_other)); - - if(cap_len < dataoff) - { - if (ScLogVerbose()) - { - ErrorMessage("Captured data length < FDDI header length! " - "(%d %d bytes)\n", cap_len, dataoff); - PREPROC_PROFILE_END(decodePerfStats); - return; - } - } - } - - /* - * 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)) - { - DEBUG_WRAP( - DebugMessage(DEBUG_DECODE, - "This FDDI Packet isn't an IP/ARP packet...\n"); - ); - PREPROC_PROFILE_END(decodePerfStats); - return; - } - - cap_len -= dataoff; - - switch(htons(p->fddiiparp->ethertype)) - { - case ETHERNET_TYPE_IP: - DEBUG_WRAP(DebugMessage(DEBUG_DECODE, "Decoding IP\n");); - DecodeIP(p->pkt + dataoff, cap_len, p); - PREPROC_PROFILE_END(decodePerfStats); - return; - - case ETHERNET_TYPE_ARP: - case ETHERNET_TYPE_REVARP: - DEBUG_WRAP(DebugMessage(DEBUG_DECODE, "Decoding ARP\n");); - dc.arp++; - - PREPROC_PROFILE_END(decodePerfStats); - return; - - case ETHERNET_TYPE_8021Q: - DecodeVlan(p->pkt + dataoff, cap_len, p); - PREPROC_PROFILE_END(decodePerfStats); - return; - - - default: - DEBUG_WRAP(DebugMessage(DEBUG_DECODE, "Unknown network protocol: %d\n", - htons(p->fddiiparp->ethertype)); - ); - // TBD add decoder drop event for unknown fddi/eth type - dc.other++; - - PREPROC_PROFILE_END(decodePerfStats); - return; - } - - PREPROC_PROFILE_END(decodePerfStats); - return; -} - -#ifdef DLT_LINUX_SLL -/* - * Function: DecodeLinuxSLLPkt(Packet *, char *, DAQ_PktHdr_t*, uint8_t*) - * - * Purpose: Decode those fun loving LinuxSLL (linux cooked sockets) - * 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 DecodeLinuxSLLPkt(Packet * p, const DAQ_PktHdr_t * pkthdr, const uint8_t * pkt) -{ - uint32_t cap_len = pkthdr->caplen; - PROFILE_VARS; - - PREPROC_PROFILE_START(decodePerfStats); - - dc.total_processed++; - - memset(p, 0, PKT_ZERO_LEN); - - p->pkth = pkthdr; - p->pkt = pkt; - - DEBUG_WRAP(DebugMessage(DEBUG_DECODE,"Packet!\n"); - DebugMessage(DEBUG_DECODE, "caplen: %lu pktlen: %lu\n", - (unsigned long)cap_len, (unsigned long)pkthdr->pktlen);); - - /* do a little validation */ - if(cap_len < SLL_HDR_LEN) - { - if (ScLogVerbose()) - { - ErrorMessage("Captured data length < SLL header length (your " - "libpcap is broken?)! (%d bytes)\n", cap_len); - } - PREPROC_PROFILE_END(decodePerfStats); - return; - } - /* lay the ethernet structure over the packet data */ - p->sllh = (SLLHdr *) pkt; - - /* grab out the network type */ - switch(ntohs(p->sllh->sll_protocol)) - { - case ETHERNET_TYPE_IP: - DEBUG_WRAP(DebugMessage(DEBUG_DECODE, - "IP datagram size calculated to be %lu bytes\n", - (unsigned long)(cap_len - SLL_HDR_LEN));); - - DecodeIP(p->pkt + SLL_HDR_LEN, cap_len - SLL_HDR_LEN, p); - PREPROC_PROFILE_END(decodePerfStats); - return; - - case ETHERNET_TYPE_ARP: - case ETHERNET_TYPE_REVARP: - DecodeARP(p->pkt + SLL_HDR_LEN, cap_len - SLL_HDR_LEN, p); - PREPROC_PROFILE_END(decodePerfStats); - return; - - case ETHERNET_TYPE_IPV6: - DecodeIPV6(p->pkt + SLL_HDR_LEN, (cap_len - SLL_HDR_LEN), p); - PREPROC_PROFILE_END(decodePerfStats); - return; - - case ETHERNET_TYPE_IPX: - DecodeIPX(p->pkt + SLL_HDR_LEN, (cap_len - SLL_HDR_LEN), p); - PREPROC_PROFILE_END(decodePerfStats); - return; - - case LINUX_SLL_P_802_3: - DEBUG_WRAP(DebugMessage(DEBUG_DATALINK, - "Linux SLL P 802.3 is not supported.\n");); - // TBD add decoder drop event for unsupported linux sll p 802.3 - dc.other++; - PREPROC_PROFILE_END(decodePerfStats); - return; - - case LINUX_SLL_P_802_2: - DEBUG_WRAP(DebugMessage(DEBUG_DATALINK, - "Linux SLL P 802.2 is not supported.\n");); - // TBD add decoder drop event for unsupported linux sll p 802.2 - dc.other++; - PREPROC_PROFILE_END(decodePerfStats); - return; - - case ETHERNET_TYPE_8021Q: - DecodeVlan(p->pkt + SLL_HDR_LEN, cap_len - SLL_HDR_LEN, p); - PREPROC_PROFILE_END(decodePerfStats); - return; - - default: - /* shouldn't go here unless pcap library changes again */ - /* should be a DECODE generated alert */ - DEBUG_WRAP(DebugMessage(DEBUG_DATALINK,"(Unknown) %X is not supported. " - "(need tcpdump snapshots to test. Please contact us)\n", - p->sllh->sll_protocol);); - // TBD add decoder drop event for unknown sll encapsulation - dc.other++; - PREPROC_PROFILE_END(decodePerfStats); - return; - } - - PREPROC_PROFILE_END(decodePerfStats); - return; -} -#endif /* DLT_LINUX_SLL */ - -/* - * Function: DecodeOldPflog(Packet *, DAQ_PktHdr_t *, uint8_t *) - * - * Purpose: Pass old pflog format device packets off to IP or IP6 -fleck - * - * Arguments: p => pointer to the decoded packet struct - * pkthdr => ptr to the packet header - * pkt => pointer to the packet data - * - * Returns: void function - * - */ -void DecodeOldPflog(Packet * p, const DAQ_PktHdr_t * pkthdr, const uint8_t * pkt) -{ - uint32_t cap_len = pkthdr->caplen; - PROFILE_VARS; - - PREPROC_PROFILE_START(decodePerfStats); - - dc.total_processed++; - - memset(p, 0, PKT_ZERO_LEN); - - p->pkth = pkthdr; - p->pkt = pkt; - - DEBUG_WRAP(DebugMessage(DEBUG_DECODE, "Packet!\n"); - DebugMessage(DEBUG_DECODE, "caplen: %lu pktlen: %lu\n", - (unsigned long)cap_len, (unsigned long)pkthdr->pktlen);); - - /* do a little validation */ - if(cap_len < PFLOG1_HDRLEN) - { - if (ScLogVerbose()) - { - ErrorMessage("Captured data length < Pflog header length! " - "(%d bytes)\n", cap_len); - } - PREPROC_PROFILE_END(decodePerfStats); - return; - } - - /* lay the pf header structure over the packet data */ - p->pf1h = (Pflog1Hdr*)pkt; - - /* get the network type - should only be AF_INET or AF_INET6 */ - switch(ntohl(p->pf1h->af)) - { - case AF_INET: /* IPv4 */ - DEBUG_WRAP(DebugMessage(DEBUG_DECODE, "IP datagram size calculated to be %lu " - "bytes\n", (unsigned long)(cap_len - PFLOG1_HDRLEN));); - - DecodeIP(p->pkt + PFLOG1_HDRLEN, cap_len - PFLOG1_HDRLEN, p); - PREPROC_PROFILE_END(decodePerfStats); - return; - -#if defined(AF_INET6) - case AF_INET6: /* IPv6 */ - DecodeIPV6(p->pkt + PFLOG1_HDRLEN, cap_len - PFLOG1_HDRLEN, p); - PREPROC_PROFILE_END(decodePerfStats); - return; -#endif - - default: - /* To my knowledge, pflog devices can only - * pass IP and IP6 packets. -fleck - */ - // TBD add decoder drop event for unknown old pflog network type - dc.other++; - PREPROC_PROFILE_END(decodePerfStats); - return; - } - - PREPROC_PROFILE_END(decodePerfStats); - return; -} - -/* - * Function: DecodePflog(Packet *, DAQ_PktHdr_t *, uint8_t *) - * - * Purpose: Pass pflog device packets off to IP or IP6 -fleck - * - * Arguments: p => pointer to the decoded packet struct - * pkthdr => ptr to the packet header - * pkt => pointer to the packet data - * - * Returns: void function - * - */ -void DecodePflog(Packet * p, const DAQ_PktHdr_t * pkthdr, const uint8_t * pkt) -{ - uint32_t cap_len = pkthdr->caplen; - uint8_t af, pflen; - uint32_t hlen; - uint32_t padlen = PFLOG_PADLEN; - PROFILE_VARS; - - PREPROC_PROFILE_START(decodePerfStats); - - dc.total_processed++; - - memset(p, 0, PKT_ZERO_LEN); - - p->pkth = pkthdr; - p->pkt = pkt; - - DEBUG_WRAP(DebugMessage(DEBUG_DECODE, "Packet!\n"); - DebugMessage(DEBUG_DECODE, "caplen: %lu pktlen: %lu\n", - (unsigned long)cap_len, (unsigned long)pkthdr->pktlen);); - - /* do a little validation */ - if(cap_len < PFLOG2_HDRMIN) - { - if (ScLogVerbose()) - { - ErrorMessage("Captured data length < minimum Pflog length! " - "(%d < %lu)\n", cap_len, (unsigned long)PFLOG2_HDRMIN); - } - PREPROC_PROFILE_END(decodePerfStats); - return; - } - - /* lay the pf header structure over the packet data */ - switch(*((uint8_t*)pkt)) - { - case PFLOG2_HDRMIN: - p->pf2h = (Pflog2Hdr*)pkt; - pflen = p->pf2h->length; - hlen = PFLOG2_HDRLEN; - af = p->pf2h->af; - break; - case PFLOG3_HDRMIN: - p->pf3h = (Pflog3Hdr*)pkt; - pflen = p->pf3h->length; - hlen = PFLOG3_HDRLEN; - af = p->pf3h->af; - break; - case PFLOG4_HDRMIN: - p->pf4h = (Pflog4Hdr*)pkt; - pflen = p->pf4h->length; - hlen = PFLOG4_HDRLEN; - af = p->pf4h->af; - padlen = sizeof(p->pf4h->pad); - break; - default: - if (ScLogVerbose()) - { - ErrorMessage("unrecognized pflog header length! (%d)\n", - *((uint8_t*)pkt)); - } - dc.discards++; - PREPROC_PROFILE_END(decodePerfStats); - return; - } - - /* now that we know a little more, do a little more validation */ - if(cap_len < hlen) - { - if (ScLogVerbose()) - { - ErrorMessage("Captured data length < Pflog header length! " - "(%d < %d)\n", cap_len, hlen); - } - dc.discards++; - PREPROC_PROFILE_END(decodePerfStats); - return; - } - /* note that the pflen may exclude the padding which is always present */ - if(pflen < hlen - padlen || pflen > hlen) - { - if (ScLogVerbose()) - { - ErrorMessage("Bad Pflog header length! (%d bytes)\n", pflen); - } - dc.discards++; - PREPROC_PROFILE_END(decodePerfStats); - return; - } - DEBUG_WRAP(DebugMessage(DEBUG_DECODE, "IP datagram size calculated to be " - "%lu bytes\n", (unsigned long)(cap_len - hlen));); - - /* check the network type - should only be AF_INET or AF_INET6 */ - switch(af) - { - case AF_INET: /* IPv4 */ - DecodeIP(p->pkt + hlen, cap_len - hlen, p); - PREPROC_PROFILE_END(decodePerfStats); - return; - -#if defined(AF_INET6) - case AF_INET6: /* IPv6 */ - DecodeIPV6(p->pkt + hlen, cap_len - hlen, p); - PREPROC_PROFILE_END(decodePerfStats); - return; -#endif - - default: - /* To my knowledge, pflog devices can only - * pass IP and IP6 packets. -fleck - */ - // TBD add decoder drop event for unknown pflog network type - dc.other++; - PREPROC_PROFILE_END(decodePerfStats); - return; - } - - PREPROC_PROFILE_END(decodePerfStats); - return; -} - -/* - * Function: DecodePppPkt(Packet *, char *, DAQ_PktHdr_t*, uint8_t*) - * - * Purpose: Decode PPP traffic (either RFC1661 or RFC1662 framing). - * This really is intended to handle IPCP - * - * 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 - */ -// DecodePppPkt() and DecodePppSerialPkt() may be incorrect ... -// both skip past 2 byte protocol and then call DecodePppPktEncapsulated() -// which does the same thing. That one works inside DecodePPPoEPkt(); -void DecodePppPkt(Packet * p, const DAQ_PktHdr_t * pkthdr, const uint8_t * pkt) -{ - uint32_t cap_len = pkthdr->caplen; - int hlen = 0; - PROFILE_VARS; - - PREPROC_PROFILE_START(decodePerfStats); - - dc.total_processed++; - - memset(p, 0, PKT_ZERO_LEN); - - p->pkth = pkthdr; - p->pkt = pkt; - - DEBUG_WRAP(DebugMessage(DEBUG_DECODE, "Packet!\n");); - - if(cap_len < 2) - { - if (ScLogVerbose()) - { - ErrorMessage("Length not big enough for even a single " - "header or a one byte payload\n"); - } - PREPROC_PROFILE_END(decodePerfStats); - return; - } - - if(pkt[0] == CHDLC_ADDR_BROADCAST && pkt[1] == CHDLC_CTRL_UNNUMBERED) - { - /* - * Check for full HDLC header (rfc1662 section 3.2) - */ - hlen = 2; - } - - DecodePppPktEncapsulated(p->pkt + hlen, cap_len - hlen, p); - - PREPROC_PROFILE_END(decodePerfStats); - return; -} - -/* - * Function: DecodePppSerialPkt(Packet *, char *, DAQ_PktHdr_t*, uint8_t*) - * - * Purpose: Decode Mixed PPP/CHDLC traffic. The PPP frames will always have the - * full HDLC header. - * - * 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 DecodePppSerialPkt(Packet * p, const DAQ_PktHdr_t * pkthdr, const uint8_t * pkt) -{ - uint32_t cap_len = pkthdr->caplen; - PROFILE_VARS; - - PREPROC_PROFILE_START(decodePerfStats); - - dc.total_processed++; - - memset(p, 0, PKT_ZERO_LEN); - - p->pkth = pkthdr; - p->pkt = pkt; - - DEBUG_WRAP(DebugMessage(DEBUG_DECODE, "Packet!\n");); - - if(cap_len < PPP_HDRLEN) - { - if (ScLogVerbose()) - { - ErrorMessage("Captured data length < PPP header length" - " (%d bytes)\n", cap_len); - } - PREPROC_PROFILE_END(decodePerfStats); - return; - } - - if(pkt[0] == CHDLC_ADDR_BROADCAST && pkt[1] == CHDLC_CTRL_UNNUMBERED) - { - DecodePppPktEncapsulated(p->pkt + 2, cap_len - 2, p); - } else { - DecodeChdlcPkt(p, pkthdr, pkt); - } - - PREPROC_PROFILE_END(decodePerfStats); - return; -} - - -/* - * Function: DecodeSlipPkt(Packet *, char *, DAQ_PktHdr_t*, uint8_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, const DAQ_PktHdr_t * pkthdr, const uint8_t * pkt) -{ - uint32_t cap_len = pkthdr->caplen; - PROFILE_VARS; - - PREPROC_PROFILE_START(decodePerfStats); - - dc.total_processed++; - - memset(p, 0, PKT_ZERO_LEN); - - p->pkth = pkthdr; - p->pkt = pkt; - - DEBUG_WRAP(DebugMessage(DEBUG_DECODE, "Packet!\n");); - - /* do a little validation */ - if(cap_len < SLIP_HEADER_LEN) - { - ErrorMessage("SLIP header length < captured len! (%d bytes)\n", - cap_len); - PREPROC_PROFILE_END(decodePerfStats); - return; - } - - DecodeIP(p->pkt + SLIP_HEADER_LEN, cap_len - SLIP_HEADER_LEN, p); - PREPROC_PROFILE_END(decodePerfStats); -} - -/* - * Function: DecodeI4LRawIPPkt(Packet *, char *, DAQ_PktHdr_t*, uint8_t*) - * - * Purpose: Decodes packets coming in raw on layer 2, like PPP. Coded and - * in by Jed Pickle (thanks Jed!) and modified for a few little tweaks - * by me. - * - * 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 DecodeI4LRawIPPkt(Packet * p, const DAQ_PktHdr_t * pkthdr, const uint8_t * pkt) -{ - PROFILE_VARS; - - PREPROC_PROFILE_START(decodePerfStats); - - dc.total_processed++; - - memset(p, 0, PKT_ZERO_LEN); - - p->pkth = pkthdr; - p->pkt = pkt; - - if(p->pkth->pktlen < 2) - { - DEBUG_WRAP(DebugMessage(DEBUG_DECODE, "What the hell is this?\n");); - // TBD add decoder drop event for bad i4l raw pkt - dc.other++; - PREPROC_PROFILE_END(decodePerfStats); - return; - } - - DEBUG_WRAP(DebugMessage(DEBUG_DECODE, "Packet!\n");); - DecodeIP(pkt + 2, p->pkth->pktlen - 2, p); - - PREPROC_PROFILE_END(decodePerfStats); - return; -} - - - -/* - * Function: DecodeI4LCiscoIPPkt(Packet *, char *, - * DAQ_PktHdr_t*, uint8_t*) - * - * Purpose: Decodes packets coming in raw on layer 2, like PPP. Coded and - * in by Jed Pickle (thanks Jed!) and modified for a few little tweaks - * by me. - * - * 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 DecodeI4LCiscoIPPkt(Packet *p, const DAQ_PktHdr_t *pkthdr, const uint8_t *pkt) -{ - PROFILE_VARS; - - PREPROC_PROFILE_START(decodePerfStats); - - dc.total_processed++; - - memset(p, 0, PKT_ZERO_LEN); - - p->pkth = pkthdr; - p->pkt = pkt; - - if(p->pkth->pktlen < 4) - { - DEBUG_WRAP(DebugMessage(DEBUG_DECODE, "What the hell is this?\n");); - // TBD add decoder drop event for bad i4l cisco pkt - dc.other++; - PREPROC_PROFILE_END(decodePerfStats); - return; - } - - - DEBUG_WRAP(DebugMessage(DEBUG_DECODE, "Packet!\n");); - - DecodeIP(pkt + 4, p->pkth->caplen - 4, p); - - PREPROC_PROFILE_END(decodePerfStats); - return; -} - -/* - * Function: DecodeChdlcPkt(Packet *, char *, - * DAQ_PktHdr_t*, uint8_t*) - * - * Purpose: Decodes Cisco HDLC encapsulated packets, f.ex. from SONET. - * - * 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 DecodeChdlcPkt(Packet *p, const DAQ_PktHdr_t *pkthdr, const uint8_t *pkt) -{ - uint32_t cap_len = pkthdr->caplen; - PROFILE_VARS; - - PREPROC_PROFILE_START(decodePerfStats); - - dc.total_processed++; - - memset(p, 0, PKT_ZERO_LEN); - - p->pkth = pkthdr; - p->pkt = pkt; - - if(cap_len < CHDLC_HEADER_LEN) - { - if (ScLogVerbose()) - { - ErrorMessage("Captured data length < CHDLC header length" - " (%d bytes)\n", cap_len); - } - PREPROC_PROFILE_END(decodePerfStats); - return; - } - - DEBUG_WRAP(DebugMessage(DEBUG_DECODE, "Packet!\n");); - - if ((pkt[0] == CHDLC_ADDR_UNICAST || pkt[0] == CHDLC_ADDR_MULTICAST) && - ntohs(*(uint16_t *)&pkt[2]) == ETHERNET_TYPE_IP) - { - DecodeIP(p->pkt + CHDLC_HEADER_LEN, - cap_len - CHDLC_HEADER_LEN, p); - } else { - // TBD add decoder drop event for unsupported chdlc encapsulation - dc.other++; - } - - PREPROC_PROFILE_END(decodePerfStats); - return; -} - -/* - * Function: DecodeEapol(uint8_t *, uint32_t, Packet *) - * - * Purpose: Decode 802.1x eapol stuff - * - * Arguments: pkt => ptr to the packet data - * len => length from here to the end of the packet - * p => pointer to decoded packet struct - * - * Returns: void function - */ -void DecodeEapol(const uint8_t * pkt, uint32_t len, Packet * p) -{ - p->eplh = (EtherEapol *) pkt; - dc.eapol++; - if(len < sizeof(EtherEapol)) - { - DecoderEvent(p, DECODE_EAPOL_TRUNCATED); - - dc.discards++; - return; - } - if (p->eplh->eaptype == EAPOL_TYPE_EAP) { - DecodeEAP(pkt + sizeof(EtherEapol), len - sizeof(EtherEapol), p); - } - else if(p->eplh->eaptype == EAPOL_TYPE_KEY) { - DecodeEapolKey(pkt + sizeof(EtherEapol), len - sizeof(EtherEapol), p); - } - return; -} - -/* - * Function: DecodeEapolKey(uint8_t *, uint32_t, Packet *) - * - * Purpose: Decode 1x key setup - * - * Arguments: pkt => ptr to the packet data - * len => length from here to the end of the packet - * p => pointer to decoded packet struct - * - * Returns: void function - */ -void DecodeEapolKey(const uint8_t * pkt, uint32_t len, Packet * p) -{ - p->eapolk = (EapolKey *) pkt; - if(len < sizeof(EapolKey)) - { - DecoderEvent(p, DECODE_EAPKEY_TRUNCATED); - - dc.discards++; - return; - } - - return; -} - -/* - * Function: DecodeEAP(uint8_t *, uint32_t, Packet *) - * - * Purpose: Decode Extensible Authentication Protocol - * - * Arguments: pkt => ptr to the packet data - * len => length from here to the end of the packet - * p => pointer to decoded packet struct - * - * Returns: void function - */ -void DecodeEAP(const uint8_t * pkt, const uint32_t len, Packet * p) -{ - p->eaph = (EAPHdr *) pkt; - if(len < sizeof(EAPHdr)) - { - DecoderEvent(p, DECODE_EAP_TRUNCATED); - - dc.discards++; - return; - } - if (p->eaph->code == EAP_CODE_REQUEST || - p->eaph->code == EAP_CODE_RESPONSE) { - p->eaptype = pkt + sizeof(EAPHdr); - } - return; -} - -/* - * Function: DecodeIPX(uint8_t *, uint32_t) - * - * Purpose: Well, it doesn't do much of anything right now... - * - * Arguments: pkt => ptr to the packet data - * len => length from here to the end of the packet - * - * Returns: void function - * - */ -void DecodeIPX(const uint8_t*, uint32_t, Packet *p) -{ - DEBUG_WRAP(DebugMessage(DEBUG_DECODE, "IPX is not supported.\n");); - - dc.ipx++; - - if (p->greh != NULL) - dc.gre_ipx++; -} - -#ifdef DLT_ENC -/* see http://sourceforge.net/mailarchive/message.php?msg_id=1000380 */ -/* - * Function: DecodeEncPkt(Packet *, DAQ_PktHdr_t *, uint8_t *) - * - * Purpose: Decapsulate packets of type DLT_ENC. - * XXX Are these always going to be IP in IP? - * - * Arguments: p => pointer to decoded packet struct - * pkthdr => pointer to the packet header - * pkt => pointer to the real live packet data - */ -void DecodeEncPkt(Packet *p, const DAQ_PktHdr_t *pkthdr, const uint8_t *pkt) -{ - uint32_t cap_len = pkthdr->caplen; - struct enc_header *enc_h; - PROFILE_VARS; - - PREPROC_PROFILE_START(decodePerfStats); - - dc.total_processed++; - - memset(p, 0, PKT_ZERO_LEN); - p->pkth = pkthdr; - p->pkt = pkt; - - if (cap_len < ENC_HEADER_LEN) - { - if (ScLogVerbose()) - { - ErrorMessage("Captured data length < Encap header length! (%d bytes)\n", - cap_len); - } - PREPROC_PROFILE_END(decodePerfStats); - return; - } - - enc_h = (struct enc_header *)p->pkt; - if (enc_h->af == AF_INET) - { - DecodeIP(p->pkt + ENC_HEADER_LEN + IP_HEADER_LEN, - cap_len - ENC_HEADER_LEN - IP_HEADER_LEN, p); - } - else - { - ErrorMessage("WARNING: Unknown address family (af: 0x%x).\n", - enc_h->af); - } - PREPROC_PROFILE_END(decodePerfStats); - return; -} -#endif /* DLT_ENC */ - -#endif // NO_NON_ETHER_DECODER - diff --git a/src/protocols/decode.h b/src/protocols/decode.h deleted file mode 100644 index dd2329094..000000000 --- a/src/protocols/decode.h +++ /dev/null @@ -1,721 +0,0 @@ -/* -** Copyright (C) 2014 Cisco and/or its affiliates. All rights reserved. -** Copyright (C) 2002-2013 Sourcefire, Inc. -** Copyright (C) 1998-2002 Martin Roesch -** -** This program is free software; you can redistribute it and/or modify -** it under the terms of the GNU General Public License Version 2 as -** published by the Free Software Foundation. You may not use, modify or -** distribute this program under any other version of the GNU General -** Public License. -** -** 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#ifndef DECODE_H -#define DECODE_H - -/* I N C L U D E S **********************************************************/ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include -#include - -#include -#include -#include -#include - -#ifndef IFNAMSIZ -#define IFNAMESIZ MAX_ADAPTER_NAME -#endif - -extern "C" { -#include -#include -} - -#include "snort_types.h" -#include "protocols/packet.h" -#include "profiler.h" - -/* D E F I N E S ************************************************************/ - -#define ETHERNET_MTU 1500 -#define ETHERNET_TYPE_IP 0x0800 -#define ETHERNET_TYPE_ARP 0x0806 -#define ETHERNET_TYPE_REVARP 0x8035 -#define ETHERNET_TYPE_EAPOL 0x888e -#define ETHERNET_TYPE_IPV6 0x86dd -#define ETHERNET_TYPE_IPX 0x8137 -#define ETHERNET_TYPE_PPPoE_DISC 0x8863 /* discovery stage */ -#define ETHERNET_TYPE_PPPoE_SESS 0x8864 /* session stage */ -#define ETHERNET_TYPE_8021Q 0x8100 -#define ETHERNET_TYPE_LOOP 0x9000 -#define ETHERNET_TYPE_MPLS_UNICAST 0x8847 -#define ETHERNET_TYPE_MPLS_MULTICAST 0x8848 -#define ETHERNET_TYPE_ERSPAN_TYPE2 0x88be -#define ETHERNET_TYPE_ERSPAN_TYPE3 0x22eb - -#define ETH_DSAP_SNA 0x08 /* SNA */ -#define ETH_SSAP_SNA 0x00 /* SNA */ -#define ETH_DSAP_STP 0x42 /* Spanning Tree Protocol */ -#define ETH_SSAP_STP 0x42 /* Spanning Tree Protocol */ -#define ETH_DSAP_IP 0xaa /* IP */ -#define ETH_SSAP_IP 0xaa /* IP */ - -#define ETH_ORG_CODE_ETHR 0x000000 /* Encapsulated Ethernet */ -#define ETH_ORG_CODE_CDP 0x00000c /* Cisco Discovery Proto */ - -#define ETHERNET_HEADER_LEN 14 -#define ETHERNET_MAX_LEN_ENCAP 1518 /* 802.3 (+LLC) or ether II ? */ -#define PPPOE_HEADER_LEN 6 - -#define VLAN_HEADER_LEN 4 - -#ifndef NO_NON_ETHER_DECODER -#define MINIMAL_TOKENRING_HEADER_LEN 22 -#define MINIMAL_IEEE80211_HEADER_LEN 10 /* Ack frames and others */ -#define IEEE802_11_DATA_HDR_LEN 24 /* Header for data packets */ -#define TR_HLEN MINIMAL_TOKENRING_HEADER_LEN -#define TOKENRING_LLC_LEN 8 -#define SLIP_HEADER_LEN 16 - -/* Frame type/subype combinations with version = 0 */ - /*** FRAME TYPE ***** HEX **** SUBTYPE TYPE DESCRIPT ********/ -#define WLAN_TYPE_MGMT_ASREQ 0x0 /* 0000 00 Association Req */ -#define WLAN_TYPE_MGMT_ASRES 0x10 /* 0001 00 Assocaition Res */ -#define WLAN_TYPE_MGMT_REREQ 0x20 /* 0010 00 Reassoc. Req. */ -#define WLAN_TYPE_MGMT_RERES 0x30 /* 0011 00 Reassoc. Resp. */ -#define WLAN_TYPE_MGMT_PRREQ 0x40 /* 0100 00 Probe Request */ -#define WLAN_TYPE_MGMT_PRRES 0x50 /* 0101 00 Probe Response */ -#define WLAN_TYPE_MGMT_BEACON 0x80 /* 1000 00 Beacon */ -#define WLAN_TYPE_MGMT_ATIM 0x90 /* 1001 00 ATIM message */ -#define WLAN_TYPE_MGMT_DIS 0xa0 /* 1010 00 Disassociation */ -#define WLAN_TYPE_MGMT_AUTH 0xb0 /* 1011 00 Authentication */ -#define WLAN_TYPE_MGMT_DEAUTH 0xc0 /* 1100 00 Deauthentication*/ - -#define WLAN_TYPE_CONT_PS 0xa4 /* 1010 01 Power Save */ -#define WLAN_TYPE_CONT_RTS 0xb4 /* 1011 01 Request to send */ -#define WLAN_TYPE_CONT_CTS 0xc4 /* 1100 01 Clear to sene */ -#define WLAN_TYPE_CONT_ACK 0xd4 /* 1101 01 Acknowledgement */ -#define WLAN_TYPE_CONT_CFE 0xe4 /* 1110 01 Cont. Free end */ -#define WLAN_TYPE_CONT_CFACK 0xf4 /* 1111 01 CF-End + CF-Ack */ - -#define WLAN_TYPE_DATA_DATA 0x08 /* 0000 10 Data */ -#define WLAN_TYPE_DATA_DTCFACK 0x18 /* 0001 10 Data + CF-Ack */ -#define WLAN_TYPE_DATA_DTCFPL 0x28 /* 0010 10 Data + CF-Poll */ -#define WLAN_TYPE_DATA_DTACKPL 0x38 /* 0011 10 Data+CF-Ack+CF-Pl */ -#define WLAN_TYPE_DATA_NULL 0x48 /* 0100 10 Null (no data) */ -#define WLAN_TYPE_DATA_CFACK 0x58 /* 0101 10 CF-Ack (no data)*/ -#define WLAN_TYPE_DATA_CFPL 0x68 /* 0110 10 CF-Poll (no data)*/ -#define WLAN_TYPE_DATA_ACKPL 0x78 /* 0111 10 CF-Ack+CF-Poll */ - -/*** Flags for IEEE 802.11 Frame Control ***/ -/* The following are designed to be bitwise-AND-d in an 8-bit u_char */ -#define WLAN_FLAG_TODS 0x0100 /* To DS Flag 10000000 */ -#define WLAN_FLAG_FROMDS 0x0200 /* From DS Flag 01000000 */ -#define WLAN_FLAG_FRAG 0x0400 /* More Frag 00100000 */ -#define WLAN_FLAG_RETRY 0x0800 /* Retry Flag 00010000 */ -#define WLAN_FLAG_PWRMGMT 0x1000 /* Power Mgmt. 00001000 */ -#define WLAN_FLAG_MOREDAT 0x2000 /* More Data 00000100 */ -#define WLAN_FLAG_WEP 0x4000 /* Wep Enabled 00000010 */ -#define WLAN_FLAG_ORDER 0x8000 /* Strict Order 00000001 */ - -/* IEEE 802.1x eapol types */ -#define EAPOL_TYPE_EAP 0x00 /* EAP packet */ -#define EAPOL_TYPE_START 0x01 /* EAPOL start */ -#define EAPOL_TYPE_LOGOFF 0x02 /* EAPOL Logoff */ -#define EAPOL_TYPE_KEY 0x03 /* EAPOL Key */ -#define EAPOL_TYPE_ASF 0x04 /* EAPOL Encapsulated ASF-Alert */ - -/* Extensible Authentication Protocol Codes RFC 2284*/ -#define EAP_CODE_REQUEST 0x01 -#define EAP_CODE_RESPONSE 0x02 -#define EAP_CODE_SUCCESS 0x03 -#define EAP_CODE_FAILURE 0x04 -/* EAP Types */ -#define EAP_TYPE_IDENTITY 0x01 -#define EAP_TYPE_NOTIFY 0x02 -#define EAP_TYPE_NAK 0x03 -#define EAP_TYPE_MD5 0x04 -#define EAP_TYPE_OTP 0x05 -#define EAP_TYPE_GTC 0x06 -#define EAP_TYPE_TLS 0x0d -#endif // NO_NON_ETHER_DECODER - -/* Cisco HDLC header values */ -#define CHDLC_HEADER_LEN 4 -#define CHDLC_ADDR_UNICAST 0x0f -#define CHDLC_ADDR_MULTICAST 0x8f -#define CHDLC_ADDR_BROADCAST 0xff -#define CHDLC_CTRL_UNNUMBERED 0x03 - -/* Teredo values */ -#define TEREDO_PORT 3544 -#define TEREDO_INDICATOR_ORIGIN 0x00 -#define TEREDO_INDICATOR_ORIGIN_LEN 8 -#define TEREDO_INDICATOR_AUTH 0x01 -#define TEREDO_INDICATOR_AUTH_MIN_LEN 13 -#define TEREDO_MIN_LEN 2 - -/* GTP values */ - -#define GTP_MIN_LEN 8 -#define GTP_V0_HEADER_LEN 20 -#define GTP_V1_HEADER_LEN 12 -/* ESP constants */ -#define ESP_HEADER_LEN 8 -#define ESP_AUTH_DATA_LEN 12 -#define ESP_TRAILER_LEN 2 - -#define MAX_PORTS 65536 - -/* ppp header structure - * - * Actually, this is the header for RFC1332 Section 3 - * IPCP Configuration Options for sending IP datagrams over a PPP link - * - */ -struct ppp_header { - unsigned char address; - unsigned char control; - unsigned short protocol; -}; - -#ifndef PPP_HDRLEN - #define PPP_HDRLEN sizeof(struct ppp_header) -#endif - -#define PPP_IP 0x0021 /* Internet Protocol */ -#define PPP_IPV6 0x0057 /* Internet Protocol v6 */ -#define PPP_VJ_COMP 0x002d /* VJ compressed TCP/IP */ -#define PPP_VJ_UCOMP 0x002f /* VJ uncompressed TCP/IP */ -#define PPP_IPX 0x002b /* Novell IPX Protocol */ - -/* otherwise defined in /usr/include/ppp_defs.h */ -#ifndef PPP_MTU - #define PPP_MTU 1500 -#endif - -/* NULL aka LoopBack interfaces */ -#define NULL_HDRLEN 4 - -/* enc interface */ -struct enc_header { - uint32_t af; - uint32_t spi; - uint32_t flags; -}; -#define ENC_HEADER_LEN 12 - -/* otherwise defined in /usr/include/ppp_defs.h */ -#define IP_HEADER_LEN 20 -#define TCP_HEADER_LEN 20 -#define UDP_HEADER_LEN 8 -#define ICMP_HEADER_LEN 4 -#define ICMP_NORMAL_LEN 8 - -#define IP_OPTMAX 40 -#define IP6_EXTMAX 8 -#define TCP_OPTLENMAX 40 /* (((2^4) - 1) * 4 - TCP_HEADER_LEN) */ - -#ifndef IP_MAXPACKET -#define IP_MAXPACKET 65535 /* maximum packet size */ -#endif /* IP_MAXPACKET */ - - -/* http://www.iana.org/assignments/ipv6-parameters - * - * IPv6 Options (not Extension Headers) - */ -#define IP6_OPT_TUNNEL_ENCAP 0x04 -#define IP6_OPT_QUICK_START 0x06 -#define IP6_OPT_CALIPSO 0x07 -#define IP6_OPT_HOME_ADDRESS 0xC9 -#define IP6_OPT_ENDPOINT_IDENT 0x8A - -// these are bits in th_flags: -#define TH_FIN 0x01 -#define TH_SYN 0x02 -#define TH_RST 0x04 -#define TH_PUSH 0x08 -#define TH_ACK 0x10 -#define TH_URG 0x20 -#define TH_ECE 0x40 -#define TH_CWR 0x80 -#define TH_RES2 TH_ECE // TBD TH_RES* should be deleted (see log.c) -#define TH_RES1 TH_CWR -#define TH_NORESERVED (TH_FIN|TH_SYN|TH_RST|TH_PUSH|TH_ACK|TH_URG) - -// these are bits in th_offx2: -#define TH_RSV 0x0E // reserved bits -#define TH_NS 0x01 // ECN nonce bit - -/* http://www.iana.org/assignments/tcp-parameters - * - * tcp options stuff. used to be in but it breaks - * things on AIX - */ -#define TCPOPT_EOL 0 /* End of Option List [RFC793] */ -#define TCPOLEN_EOL 1 /* Always one byte */ - -#define TCPOPT_NOP 1 /* No-Option [RFC793] */ -#define TCPOLEN_NOP 1 /* Always one byte */ - -#define TCPOPT_MAXSEG 2 /* Maximum Segment Size [RFC793] */ -#define TCPOLEN_MAXSEG 4 /* Always 4 bytes */ - -#define TCPOPT_WSCALE 3 /* Window scaling option [RFC1323] */ -#define TCPOLEN_WSCALE 3 /* 1 byte with logarithmic values */ - -#define TCPOPT_SACKOK 4 /* Experimental [RFC2018]*/ -#define TCPOLEN_SACKOK 2 - -#define TCPOPT_SACK 5 /* Experimental [RFC2018] variable length */ - -#define TCPOPT_ECHO 6 /* Echo (obsoleted by option 8) [RFC1072] */ -#define TCPOLEN_ECHO 6 /* 6 bytes */ - -#define TCPOPT_ECHOREPLY 7 /* Echo Reply (obsoleted by option 8)[RFC1072] */ -#define TCPOLEN_ECHOREPLY 6 /* 6 bytes */ - -#define TCPOPT_TIMESTAMP 8 /* Timestamp [RFC1323], 10 bytes */ -#define TCPOLEN_TIMESTAMP 10 - -#define TCPOPT_PARTIAL_PERM 9 /* Partial Order Permitted/ Experimental [RFC1693] */ -#define TCPOLEN_PARTIAL_PERM 2 /* Partial Order Permitted/ Experimental [RFC1693] */ - -#define TCPOPT_PARTIAL_SVC 10 /* Partial Order Profile [RFC1693] */ -#define TCPOLEN_PARTIAL_SVC 3 /* 3 bytes long -- Experimental */ - -/* atleast decode T/TCP options... */ -#define TCPOPT_CC 11 /* T/TCP Connection count [RFC1644] */ -#define TCPOPT_CC_NEW 12 /* CC.NEW [RFC1644] */ -#define TCPOPT_CC_ECHO 13 /* CC.ECHO [RFC1644] */ -#define TCPOLEN_CC 6 /* page 17 of rfc1644 */ -#define TCPOLEN_CC_NEW 6 /* page 17 of rfc1644 */ -#define TCPOLEN_CC_ECHO 6 /* page 17 of rfc1644 */ - -#define TCPOPT_ALTCSUM 15 /* TCP Alternate Checksum Data [RFC1146], variable length */ -#define TCPOPT_SKEETER 16 /* Skeeter [Knowles] */ -#define TCPOPT_BUBBA 17 /* Bubba [Knowles] */ - -#define TCPOPT_TRAILER_CSUM 18 /* Trailer Checksum Option [Subbu & Monroe] */ -#define TCPOLEN_TRAILER_CSUM 3 - -#define TCPOPT_MD5SIG 19 /* MD5 Signature Option [RFC2385] */ -#define TCPOLEN_MD5SIG 18 - -/* Space Communications Protocol Standardization */ -#define TCPOPT_SCPS 20 /* Capabilities [Scott] */ -#define TCPOPT_SELNEGACK 21 /* Selective Negative Acknowledgements [Scott] */ -#define TCPOPT_RECORDBOUND 22 /* Record Boundaries [Scott] */ -#define TCPOPT_CORRUPTION 23 /* Corruption experienced [Scott] */ - -#define TCPOPT_SNAP 24 /* SNAP [Sukonnik] -- anyone have info?*/ -#define TCPOPT_UNASSIGNED 25 /* Unassigned (released 12/18/00) */ -#define TCPOPT_COMPRESSION 26 /* TCP Compression Filter [Bellovin] */ -/* http://www.research.att.com/~smb/papers/draft-bellovin-tcpcomp-00.txt*/ - -#define TCPOPT_AUTH 29 /* [RFC5925] - The TCP Authentication Option - Intended to replace MD5 Signature Option [RFC2385] */ - -#define TCP_OPT_TRUNC -1 -#define TCP_OPT_BADLEN -2 - -/* Why are these lil buggers here? Never Used. -- cmg */ -#define TCPOLEN_TSTAMP_APPA (TCPOLEN_TIMESTAMP+2) /* appendix A / rfc 1323 */ -#define TCPOPT_TSTAMP_HDR \ - (TCPOPT_NOP<<24|TCPOPT_NOP<<16|TCPOPT_TIMESTAMP<<8|TCPOLEN_TIMESTAMP) - -/* - * Default maximum segment size for TCP. - * With an IP MSS of 576, this is 536, - * but 512 is probably more convenient. - * This should be defined as MIN(512, IP_MSS - sizeof (struct tcpiphdr)). - */ - -#ifndef TCP_MSS - #define TCP_MSS 512 -#endif - -#ifndef TCP_MAXWIN - #define TCP_MAXWIN 65535 /* largest value for (unscaled) window */ -#endif - -#ifndef TCP_MAX_WINSHIFT - #define TCP_MAX_WINSHIFT 14 /* maximum window shift */ -#endif - -/* - * User-settable options (used with setsockopt). - */ -#ifndef TCP_NODELAY - #define TCP_NODELAY 0x01 /* don't delay send to coalesce packets */ -#endif - -#ifndef TCP_MAXSEG - #define TCP_MAXSEG 0x02 /* set maximum segment size */ -#endif - -#define SOL_TCP 6 /* TCP level */ - - - -#define L2TP_PORT 1701 -#define DHCP_CLIENT_PORT 68 -#define DHCP_SERVER_PORT 67 - -#ifndef NO_NON_ETHER_DECODER -/* Start Token Ring */ -#define TR_ALEN 6 /* octets in an Ethernet header */ -#define IPARP_SAP 0xaa - -#define AC 0x10 -#define LLC_FRAME 0x40 - -#define TRMTU 2000 /* 2000 bytes */ -#define TR_RII 0x80 -#define TR_RCF_DIR_BIT 0x80 -#define TR_RCF_LEN_MASK 0x1f00 -#define TR_RCF_BROADCAST 0x8000 /* all-routes broadcast */ -#define TR_RCF_LIMITED_BROADCAST 0xC000 /* single-route broadcast */ -#define TR_RCF_FRAME2K 0x20 -#define TR_RCF_BROADCAST_MASK 0xC000 -/* End Token Ring */ - -/* Start FDDI */ -#define FDDI_ALLC_LEN 13 -#define FDDI_ALEN 6 -#define FDDI_MIN_HLEN (FDDI_ALLC_LEN + 3) - -#define FDDI_DSAP_SNA 0x08 /* SNA */ -#define FDDI_SSAP_SNA 0x00 /* SNA */ -#define FDDI_DSAP_STP 0x42 /* Spanning Tree Protocol */ -#define FDDI_SSAP_STP 0x42 /* Spanning Tree Protocol */ -#define FDDI_DSAP_IP 0xaa /* IP */ -#define FDDI_SSAP_IP 0xaa /* IP */ - -#define FDDI_ORG_CODE_ETHR 0x000000 /* Encapsulated Ethernet */ -#define FDDI_ORG_CODE_CDP 0x00000c /* Cisco Discovery - * Proto(?) */ - -#define ETHERNET_TYPE_CDP 0x2000 /* Cisco Discovery Protocol */ -/* End FDDI */ -#endif // NO_NON_ETHER_DECODER - -#define ARPOP_REQUEST 1 /* ARP request */ -#define ARPOP_REPLY 2 /* ARP reply */ -#define ARPOP_RREQUEST 3 /* RARP request */ -#define ARPOP_RREPLY 4 /* RARP reply */ - -/* PPPoE types */ -#define PPPoE_CODE_SESS 0x00 /* PPPoE session */ -#define PPPoE_CODE_PADI 0x09 /* PPPoE Active Discovery Initiation */ -#define PPPoE_CODE_PADO 0x07 /* PPPoE Active Discovery Offer */ -#define PPPoE_CODE_PADR 0x19 /* PPPoE Active Discovery Request */ -#define PPPoE_CODE_PADS 0x65 /* PPPoE Active Discovery Session-confirmation */ -#define PPPoE_CODE_PADT 0xa7 /* PPPoE Active Discovery Terminate */ - -/* PPPoE tag types */ -#define PPPoE_TAG_END_OF_LIST 0x0000 -#define PPPoE_TAG_SERVICE_NAME 0x0101 -#define PPPoE_TAG_AC_NAME 0x0102 -#define PPPoE_TAG_HOST_UNIQ 0x0103 -#define PPPoE_TAG_AC_COOKIE 0x0104 -#define PPPoE_TAG_VENDOR_SPECIFIC 0x0105 -#define PPPoE_TAG_RELAY_SESSION_ID 0x0110 -#define PPPoE_TAG_SERVICE_NAME_ERROR 0x0201 -#define PPPoE_TAG_AC_SYSTEM_ERROR 0x0202 -#define PPPoE_TAG_GENERIC_ERROR 0x0203 - -#define MPLS_PAYLOADTYPE_ETHERNET 1 -#define MPLS_PAYLOADTYPE_IPV4 2 -#define MPLS_PAYLOADTYPE_IPV6 3 -#define MPLS_PAYLOADTYPE_ERROR -1 -#define DEFAULT_MPLS_PAYLOADTYPE MPLS_PAYLOADTYPE_IPV4 -#define DEFAULT_LABELCHAIN_LENGTH -1 - -#define ICMP_ECHOREPLY 0 /* Echo Reply */ -#define ICMP_DEST_UNREACH 3 /* Destination Unreachable */ -#define ICMP_SOURCE_QUENCH 4 /* Source Quench */ -#define ICMP_REDIRECT 5 /* Redirect (change route) */ -#define ICMP_ECHO 8 /* Echo Request */ -#define ICMP_ROUTER_ADVERTISE 9 /* Router Advertisement */ -#define ICMP_ROUTER_SOLICIT 10 /* Router Solicitation */ -#define ICMP_TIME_EXCEEDED 11 /* Time Exceeded */ -#define ICMP_PARAMETERPROB 12 /* Parameter Problem */ -#define ICMP_TIMESTAMP 13 /* Timestamp Request */ -#define ICMP_TIMESTAMPREPLY 14 /* Timestamp Reply */ -#define ICMP_INFO_REQUEST 15 /* Information Request */ -#define ICMP_INFO_REPLY 16 /* Information Reply */ -#define ICMP_ADDRESS 17 /* Address Mask Request */ -#define ICMP_ADDRESSREPLY 18 /* Address Mask Reply */ -#define NR_ICMP_TYPES 18 - -/* Codes for ICMP UNREACHABLES */ -#define ICMP_NET_UNREACH 0 /* Network Unreachable */ -#define ICMP_HOST_UNREACH 1 /* Host Unreachable */ -#define ICMP_PROT_UNREACH 2 /* Protocol Unreachable */ -#define ICMP_PORT_UNREACH 3 /* Port Unreachable */ -#define ICMP_FRAG_NEEDED 4 /* Fragmentation Needed/DF set */ -#define ICMP_SR_FAILED 5 /* Source Route failed */ -#define ICMP_NET_UNKNOWN 6 -#define ICMP_HOST_UNKNOWN 7 -#define ICMP_HOST_ISOLATED 8 -#define ICMP_PKT_FILTERED_NET 9 -#define ICMP_PKT_FILTERED_HOST 10 -#define ICMP_NET_UNR_TOS 11 -#define ICMP_HOST_UNR_TOS 12 -#define ICMP_PKT_FILTERED 13 /* Packet filtered */ -#define ICMP_PREC_VIOLATION 14 /* Precedence violation */ -#define ICMP_PREC_CUTOFF 15 /* Precedence cut off */ -#define NR_ICMP_UNREACH 15 /* instead of hardcoding immediate - * value */ - -#define ICMP_REDIR_NET 0 -#define ICMP_REDIR_HOST 1 -#define ICMP_REDIR_TOS_NET 2 -#define ICMP_REDIR_TOS_HOST 3 - -#define ICMP_TIMEOUT_TRANSIT 0 -#define ICMP_TIMEOUT_REASSY 1 - -#define ICMP_PARAM_BADIPHDR 0 -#define ICMP_PARAM_OPTMISSING 1 -#define ICMP_PARAM_BAD_LENGTH 2 - -/* ip option type codes */ -#ifndef IPOPT_EOL - #define IPOPT_EOL 0x00 -#endif - -#ifndef IPOPT_NOP - #define IPOPT_NOP 0x01 -#endif - -#ifndef IPOPT_RR - #define IPOPT_RR 0x07 -#endif - -#ifndef IPOPT_RTRALT - #define IPOPT_RTRALT 0x94 -#endif - -#ifndef IPOPT_TS - #define IPOPT_TS 0x44 -#endif - -#ifndef IPOPT_SECURITY - #define IPOPT_SECURITY 0x82 -#endif - -#ifndef IPOPT_LSRR - #define IPOPT_LSRR 0x83 -#endif - -#ifndef IPOPT_LSRR_E - #define IPOPT_LSRR_E 0x84 -#endif - -#ifndef IPOPT_ESEC - #define IPOPT_ESEC 0x85 -#endif - -#ifndef IPOPT_SATID - #define IPOPT_SATID 0x88 -#endif - -#ifndef IPOPT_SSRR - #define IPOPT_SSRR 0x89 -#endif - - -/* tcp option codes */ -#define TOPT_EOL 0x00 -#define TOPT_NOP 0x01 -#define TOPT_MSS 0x02 -#define TOPT_WS 0x03 -#define TOPT_TS 0x08 -#ifndef TCPOPT_WSCALE - #define TCPOPT_WSCALE 3 /* window scale factor (rfc1072) */ -#endif -#ifndef TCPOPT_SACKOK - #define TCPOPT_SACKOK 4 /* selective ack ok (rfc1072) */ -#endif -#ifndef TCPOPT_SACK - #define TCPOPT_SACK 5 /* selective ack (rfc1072) */ -#endif -#ifndef TCPOPT_ECHO - #define TCPOPT_ECHO 6 /* echo (rfc1072) */ -#endif -#ifndef TCPOPT_ECHOREPLY - #define TCPOPT_ECHOREPLY 7 /* echo (rfc1072) */ -#endif -#ifndef TCPOPT_TIMESTAMP - #define TCPOPT_TIMESTAMP 8 /* timestamps (rfc1323) */ -#endif -#ifndef TCPOPT_CC - #define TCPOPT_CC 11 /* T/TCP CC options (rfc1644) */ -#endif -#ifndef TCPOPT_CCNEW - #define TCPOPT_CCNEW 12 /* T/TCP CC options (rfc1644) */ -#endif -#ifndef TCPOPT_CCECHO - #define TCPOPT_CCECHO 13 /* T/TCP CC options (rfc1644) */ -#endif - -#define EXTRACT_16BITS(p) ((u_short) ntohs (*(u_short *)(p))) - -#ifdef WORDS_MUSTALIGN - -#if defined(__GNUC__) -/* force word-aligned ntohl parameter */ - #define EXTRACT_32BITS(p) ({ uint32_t __tmp; memmove(&__tmp, (p), sizeof(uint32_t)); (uint32_t) ntohl(__tmp);}) -#endif /* __GNUC__ */ - -#else - -/* allows unaligned ntohl parameter - dies w/SIGBUS on SPARCs */ - #define EXTRACT_32BITS(p) ((uint32_t) ntohl (*(uint32_t *)(p))) - -#endif /* WORDS_MUSTALIGN */ - -#if 0 -FIXIT delete me -typedef struct s_pseudoheader -{ - uint32_t sip, dip; - uint8_t zero; - uint8_t protocol; - uint16_t len; - -} PSEUDO_HDR; -#endif - -/* Default classification for decoder alerts */ -#define DECODE_CLASS 25 - -typedef struct _DecoderFlags -{ - char decode_alerts; /* if decode.c alerts are going to be enabled */ - char oversized_alert; /* alert if garbage after tcp/udp payload */ - char oversized_drop; /* alert if garbage after tcp/udp payload */ - char drop_alerts; /* drop alerts from decoder */ - char tcpopt_experiment; /* TcpOptions Decoder */ - char drop_tcpopt_experiment; /* Drop alerts from TcpOptions Decoder */ - char tcpopt_obsolete; /* Alert on obsolete TCP options */ - char drop_tcpopt_obsolete; /* Drop on alerts from obsolete TCP options */ - char tcpopt_ttcp; /* Alert on T/TCP options */ - char drop_tcpopt_ttcp; /* Drop on alerts from T/TCP options */ - char tcpopt_decode; /* alert on decoder inconsistencies */ - char drop_tcpopt_decode; /* Drop on alerts from decoder inconsistencies */ - char ipopt_decode; /* alert on decoder inconsistencies */ - char drop_ipopt_decode; /* Drop on alerts from decoder inconsistencies */ - - /* To be moved to the frag preprocessor once it supports IPv6 */ - char ipv6_bad_frag_pkt; - char bsd_icmp_frag; - char drop_bad_ipv6_frag; - -} DecoderFlags; - -#define ALERTMSG_LENGTH 256 - - -/* P R O T O T Y P E S ******************************************************/ - -// root decoders -void DecodeEthPkt(Packet *, const DAQ_PktHdr_t*, const uint8_t *); -void DecodeNullPkt(Packet *, const DAQ_PktHdr_t*, const uint8_t *); -void DecodeRawPkt(Packet *, const DAQ_PktHdr_t*, const uint8_t *); -void DecodeRawPkt6(Packet *, const DAQ_PktHdr_t*, const uint8_t *); - -// chained decoders -void DecodeARP(const uint8_t *, uint32_t, Packet *); -void DecodeEthLoopback(const uint8_t *, uint32_t, Packet *); -void DecodeVlan(const uint8_t *, const uint32_t, Packet *); -void DecodePppPktEncapsulated(const uint8_t *, const uint32_t, Packet *); -void DecodePPPoEPkt(const uint8_t *, const uint32_t, Packet *); -void DecodeIP(const uint8_t *, const uint32_t, Packet *); -void DecodeIPV6(const uint8_t *, uint32_t, Packet *); -void DecodeTCP(const uint8_t *, const uint32_t, Packet *); -void DecodeUDP(const uint8_t *, const uint32_t, Packet *); -void DecodeICMP(const uint8_t *, const uint32_t, Packet *); -void DecodeICMP6(const uint8_t *, const uint32_t, Packet *); -void DecodeICMPEmbeddedIP(const uint8_t *, const uint32_t, Packet *); -void DecodeICMPEmbeddedIP6(const uint8_t *, const uint32_t, Packet *); -void DecodeIPOptions(const uint8_t *, uint32_t, Packet *); -void DecodeTCPOptions(const uint8_t *, uint32_t, Packet *); -void DecodeTeredo(const uint8_t *, uint32_t, Packet *); -void DecodeAH(const uint8_t *, uint32_t, Packet *); -void DecodeESP(const uint8_t *, uint32_t, Packet *); -void DecodeGTP(const uint8_t *, uint32_t, Packet *); - -void DecodeGRE(const uint8_t *, const uint32_t, Packet *); -void DecodeTransBridging(const uint8_t *, const uint32_t, Packet *); -void DecoderAlertEncapsulated(Packet *, int, const char *, const uint8_t *, uint32_t); - -int isPrivateIP(uint32_t addr); -void DecodeEthOverMPLS(const uint8_t*, const uint32_t, Packet*); -void DecodeMPLS(const uint8_t*, const uint32_t, Packet*); - -#ifndef NO_NON_ETHER_DECODER -// root decoders -void DecodeTRPkt(Packet *, const DAQ_PktHdr_t*, const uint8_t *); -void DecodeFDDIPkt(Packet *, const DAQ_PktHdr_t*, const uint8_t *); -void DecodeLinuxSLLPkt(Packet *, const DAQ_PktHdr_t*, const uint8_t *); -void DecodeIEEE80211Pkt(Packet *, const DAQ_PktHdr_t*, const uint8_t *); -void DecodeSlipPkt(Packet *, const DAQ_PktHdr_t*, const uint8_t *); -void DecodeI4LRawIPPkt(Packet *, const DAQ_PktHdr_t*, const uint8_t *); -void DecodeI4LCiscoIPPkt(Packet *, const DAQ_PktHdr_t*, const uint8_t *); -void DecodeChdlcPkt(Packet *, const DAQ_PktHdr_t*, const uint8_t *); -void DecodePflog(Packet *, const DAQ_PktHdr_t*, const uint8_t *); -void DecodeOldPflog(Packet *, const DAQ_PktHdr_t*, const uint8_t *); -void DecodePppPkt(Packet *, const DAQ_PktHdr_t*, const uint8_t *); -void DecodePppSerialPkt(Packet *, const DAQ_PktHdr_t*, const uint8_t *); -void DecodeEncPkt(Packet *, const DAQ_PktHdr_t*, const uint8_t *); - -// chained decoders -void DecodeEAP(const uint8_t *, const uint32_t, Packet *); -void DecodeEapol(const uint8_t *, uint32_t, Packet *); -void DecodeEapolKey(const uint8_t *, uint32_t, Packet *); -void DecodeIPX(const uint8_t *, uint32_t, Packet *); -#endif // NO_NON_ETHER_DECODER - -void BsdFragHashInit(int max); -void BsdFragHashCleanup(void); -void BsdFragHashReset(void); - -#if defined(WORDS_MUSTALIGN) && !defined(__GNUC__) -uint32_t EXTRACT_32BITS (u_char *); -#endif /* WORDS_MUSTALIGN && !__GNUC__ */ - -/*Decode functions that need to be called once the policies are set */ -extern void DecodePolicySpecific(Packet *); - -void InitSynToMulticastDstIp(struct SnortConfig*); -void SynToMulticastDstIpDestroy( void ); - -#define SFTARGET_UNKNOWN_PROTOCOL -1 - -#ifdef PERF_PROFILING -extern THREAD_LOCAL PreprocStats decodePerfStats; -#endif - -void decoder_sum(); -void decoder_stats(); - -#endif - diff --git a/src/protocols/decode_module.cc b/src/protocols/decode_module.cc deleted file mode 100644 index f22063eb1..000000000 --- a/src/protocols/decode_module.cc +++ /dev/null @@ -1,302 +0,0 @@ -/* -** Copyright (C) 2014 Cisco and/or its affiliates. All rights reserved. -** -** This program is free software; you can redistribute it and/or modify -** it under the terms of the GNU General Public License Version 2 as -** published by the Free Software Foundation. You may not use, modify or -** distribute this program under any other version of the GNU General -** Public License. -** -** 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -// decode_module.cc author Russ Combs - -#include "decode_module.h" -#include "decode.h" -#include "parser/config_file.h" - -//------------------------------------------------------------------------- -// attributes -//------------------------------------------------------------------------- - -// FIXIT some of these could move to nap / decoder / traffic policy -static const Parameter decode_params[] = -{ - { "decode_data_link", Parameter::PT_BOOL, nullptr, "false", - "display the second layer header info" }, - - { "decode_esp", Parameter::PT_BOOL, nullptr, "false", - "enable for inspection of esp traffic that has authentication but not encryption" }, - - { "deep_teredo_inspection", Parameter::PT_BOOL, nullptr, "false", - "look for Teredo on all UDP ports (default is only 3544)" }, - - { "enable_gtp", Parameter::PT_BOOL, nullptr, "false", - "decode GTP encapsulations" }, - - { "enable_mpls_multicast", Parameter::PT_BOOL, nullptr, "false", - "enables support for MPLS multicast" }, - - { "enable_mpls_overlapping_ip", Parameter::PT_BOOL, nullptr, "false", - "enable if private network addresses overlap and must be differentiated by MPLS label(s)" }, - - // FIXIT use PT_BIT_LIST - { "gtp_ports", Parameter::PT_STRING, nullptr, - "'2152 3386'", "set GTP ports" }, - - { "max_mpls_label_chain_len", Parameter::PT_INT, "-1:", "-1", - "set MPLS stack depth" }, - - { "mpls_payload_type", Parameter::PT_ENUM, "eth | ip4 | ip6", "ip4", - "set encapsulated payload type" }, - - // see stream_paf.c for max - { "paf_max", Parameter::PT_INT, "2048:63780", "16384", - "set maximum number of TCP payload octets to reassemble at one time" }, - - { "snap_len", Parameter::PT_INT, "0:65535", "deflt", - "set snap length (same as -P)" }, - - { nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr } -}; - -//------------------------------------------------------------------------- -// rule msgs -//------------------------------------------------------------------------- - -static const RuleMap decode_rules[] = -{ - { DECODE_NOT_IPV4_DGRAM, "(decode) Not IPv4 datagram" }, - { DECODE_IPV4_INVALID_HEADER_LEN, "(decode) hlen < IP_HEADER_LEN" }, - { DECODE_IPV4_DGRAM_LT_IPHDR, "(decode) IP dgm len < IP Hdr len" }, - { DECODE_IPV4OPT_BADLEN, "(decode) Ipv4 Options found with bad lengths" }, - { DECODE_IPV4OPT_TRUNCATED, "(decode) Truncated Ipv4 Options" }, - { DECODE_IPV4_DGRAM_GT_CAPLEN, "(decode) IP dgm len > captured len" }, - - { DECODE_TCP_DGRAM_LT_TCPHDR, "(decode) TCP packet len is smaller than 20 bytes" }, - { DECODE_TCP_INVALID_OFFSET, "(decode) TCP Data Offset is less than 5" }, - { DECODE_TCP_LARGE_OFFSET, "(decode) TCP Header length exceeds packet length" }, - - { DECODE_TCPOPT_BADLEN, "(decode) Tcp Options found with bad lengths" }, - { DECODE_TCPOPT_TRUNCATED, "(decode) Truncated Tcp Options" }, - { DECODE_TCPOPT_TTCP, "(decode) T/TCP Detected" }, - { DECODE_TCPOPT_OBSOLETE, "(decode) Obsolete TCP Options found" }, - { DECODE_TCPOPT_EXPERIMENTAL, "(decode) Experimental Tcp Options found" }, - { DECODE_TCPOPT_WSCALE_INVALID, "(decode) Tcp Window Scale Option found with length > 14" }, - - { DECODE_UDP_DGRAM_LT_UDPHDR, "(decode) Truncated UDP Header" }, - { DECODE_UDP_DGRAM_INVALID_LENGTH, "(decode) Invalid UDP header, length field < 8" }, - { DECODE_UDP_DGRAM_SHORT_PACKET, "(decode) Short UDP packet, length field > payload length" }, - { DECODE_UDP_DGRAM_LONG_PACKET, "(decode) Long UDP packet, length field < payload length" }, - - { DECODE_ICMP_DGRAM_LT_ICMPHDR, "(decode) ICMP Header Truncated" }, - { DECODE_ICMP_DGRAM_LT_TIMESTAMPHDR, "(decode) ICMP Timestamp Header Truncated" }, - { DECODE_ICMP_DGRAM_LT_ADDRHDR, "(decode) ICMP Address Header Truncated" }, - { DECODE_ARP_TRUNCATED, "(decode) Truncated ARP" }, - { DECODE_EAPOL_TRUNCATED, "(decode) Truncated EAP Header" }, - { DECODE_EAPKEY_TRUNCATED, "(decode) EAP Key Truncated" }, - { DECODE_EAP_TRUNCATED, "(decode) EAP Header Truncated" }, - { DECODE_BAD_PPPOE, "(decode) Bad PPPOE frame detected" }, - { DECODE_BAD_VLAN, "(decode) Bad VLAN Frame" }, - { DECODE_BAD_VLAN_ETHLLC, "(decode) Bad LLC header" }, - { DECODE_BAD_VLAN_OTHER, "(decode) Bad Extra LLC Info" }, - { DECODE_BAD_80211_ETHLLC, "(decode) Bad 802.11 LLC header" }, - { DECODE_BAD_80211_OTHER, "(decode) Bad 802.11 Extra LLC Info" }, - - { DECODE_BAD_TRH, "(decode) Bad Token Ring Header" }, - { DECODE_BAD_TR_ETHLLC, "(decode) Bad Token Ring ETHLLC Header" }, - { DECODE_BAD_TR_MR_LEN, "(decode) Bad Token Ring MRLENHeader" }, - { DECODE_BAD_TRHMR, "(decode) Bad Token Ring MR Header" }, - - { DECODE_BAD_TRAFFIC_LOOPBACK, "(snort decoder) Bad Traffic Loopback IP" }, - { DECODE_BAD_TRAFFIC_SAME_SRCDST, "(snort decoder) Bad Traffic Same Src/Dst IP" }, - - { DECODE_GRE_DGRAM_LT_GREHDR, "(snort decoder) GRE header length > payload length" }, - { DECODE_GRE_MULTIPLE_ENCAPSULATION, "(snort decoder) Multiple encapsulations in packet" }, - { DECODE_GRE_INVALID_VERSION, "(snort decoder) Invalid GRE version" }, - { DECODE_GRE_INVALID_HEADER, "(snort decoder) Invalid GRE header" }, - { DECODE_GRE_V1_INVALID_HEADER, "(snort decoder) Invalid GRE v.1 PPTP header" }, - { DECODE_GRE_TRANS_DGRAM_LT_TRANSHDR, "(snort decoder) GRE Trans header length > payload length" }, - - { DECODE_ICMP_ORIG_IP_TRUNCATED, "(decode) ICMP Original IP Header Truncated" }, - { DECODE_ICMP_ORIG_IP_VER_MISMATCH, "(decode) ICMP version and Original IP Header versions differ" }, - { DECODE_ICMP_ORIG_DGRAM_LT_ORIG_IP, "(decode) ICMP Original Datagram Length < Original IP Header Length" }, - { DECODE_ICMP_ORIG_PAYLOAD_LT_64, "(decode) ICMP Original IP Payload < 64 bits" }, - { DECODE_ICMP_ORIG_PAYLOAD_GT_576, "(decode) ICMP Origianl IP Payload > 576 bytes" }, - { DECODE_ICMP_ORIG_IP_WITH_FRAGOFFSET, "(decode) ICMP Original IP Fragmented and Offset Not 0" }, - - { DECODE_IPV6_MIN_TTL, "(snort decoder) IPv6 packet below TTL limit" }, - { DECODE_IPV6_IS_NOT, "(snort decoder) IPv6 header claims to not be IPv6" }, - { DECODE_IPV6_TRUNCATED_EXT, "(snort decoder) IPV6 truncated extension header" }, - { DECODE_IPV6_TRUNCATED, "(snort decoder) IPV6 truncated header" }, - { DECODE_IPV6_DGRAM_LT_IPHDR, "(decode) IP dgm len < IP Hdr len" }, - { DECODE_IPV6_DGRAM_GT_CAPLEN, "(decode) IP dgm len > captured len" }, - - { DECODE_IPV6_DST_ZERO, "(decode) IPv6 packet with destination address ::0" }, - { DECODE_IPV6_SRC_MULTICAST, "(decode) IPv6 packet with multicast source address" }, - { DECODE_IPV6_DST_RESERVED_MULTICAST, "(decode) IPv6 packet with reserved multicast destination address" }, - { DECODE_IPV6_BAD_OPT_TYPE, "(decode) IPv6 header includes an undefined option type" }, - { DECODE_IPV6_BAD_MULTICAST_SCOPE, "(decode) IPv6 address includes an unassigned multicast scope value" }, - { DECODE_IPV6_BAD_NEXT_HEADER, "(decode) IPv6 header includes an invalid value for the \"next header\" field" }, - { DECODE_IPV6_ROUTE_AND_HOPBYHOP, "(decode) IPv6 header includes a routing extension header followed by a hop-by-hop header" }, - { DECODE_IPV6_TWO_ROUTE_HEADERS, "(decode) IPv6 header includes two routing extension headers" }, - { DECODE_IPV6_DSTOPTS_WITH_ROUTING, "(decode) IPv6 header has destination options followed by a routing header" }, - { DECODE_ICMPV6_TOO_BIG_BAD_MTU, "(decode) ICMPv6 packet of type 2 (message too big) with MTU field < 1280" }, - { DECODE_ICMPV6_UNREACHABLE_NON_RFC_2463_CODE, "(decode) ICMPv6 packet of type 1 (destination unreachable) with non-RFC 2463 code" }, - { DECODE_ICMPV6_SOLICITATION_BAD_CODE, "(decode) ICMPv6 router solicitation packet with a code not equal to 0" }, - { DECODE_ICMPV6_ADVERT_BAD_CODE, "(decode) ICMPv6 router advertisement packet with a code not equal to 0" }, - { DECODE_ICMPV6_SOLICITATION_BAD_RESERVED, "(decode) ICMPv6 router solicitation packet with the reserved field not equal to 0" }, - { DECODE_ICMPV6_ADVERT_BAD_REACHABLE, "(decode) ICMPv6 router advertisement packet with the reachable time field set > 1 hour" }, - - { DECODE_IPV6_TUNNELED_IPV4_TRUNCATED, "(decode) IPV6 tunneled over IPv4, IPv6 header truncated, possible Linux Kernel attack" }, - - { DECODE_IP_MULTIPLE_ENCAPSULATION, "(decode) Two or more IP (v4 and/or v6) encapsulation layers present" }, - - { DECODE_ESP_HEADER_TRUNC, "(decode) truncated Encapsulated Security Payload (ESP) header" }, - - { DECODE_IPV6_BAD_OPT_LEN, "(decode) IPv6 header includes an option which is too big for the containing header" }, - - { DECODE_IPV6_UNORDERED_EXTENSIONS, "(decode) IPv6 packet includes out-of-order extension headers" }, - { DECODE_GTP_MULTIPLE_ENCAPSULATION, "(decode) Two or more GTP encapsulation layers present" }, - { DECODE_GTP_BAD_LEN, "(decode) GTP header length is invalid" }, - { DECODE_TCP_XMAS, "(decode) XMAS Attack Detected" }, - { DECODE_TCP_NMAP_XMAS, "(decode) Nmap XMAS Attack Detected" }, - - { DECODE_DOS_NAPTHA, "(decode) DOS NAPTHA Vulnerability Detected" }, - { DECODE_SYN_TO_MULTICAST, "(decode) Bad Traffic SYN to multicast address" }, - { DECODE_ZERO_TTL, "(decode) IPV4 packet with zero TTL" }, - { DECODE_BAD_FRAGBITS, "(decode) IPV4 packet with bad frag bits (Both MF and DF set)" }, - { DECODE_UDP_IPV6_ZERO_CHECKSUM, "(decode) Invalid IPv6 UDP packet, checksum zero" }, - { DECODE_IP4_LEN_OFFSET, "(decode) IPV4 packet frag offset + length exceed maximum" }, - { DECODE_IP4_SRC_THIS_NET, "(decode) IPV4 packet from 'current net' source address" }, - { DECODE_IP4_DST_THIS_NET, "(decode) IPV4 packet to 'current net' dest address" }, - { DECODE_IP4_SRC_MULTICAST, "(decode) IPV4 packet from multicast source address" }, - { DECODE_IP4_SRC_RESERVED, "(decode) IPV4 packet from reserved source address" }, - { DECODE_IP4_DST_RESERVED, "(decode) IPV4 packet to reserved dest address" }, - { DECODE_IP4_SRC_BROADCAST, "(decode) IPV4 packet from broadcast source address" }, - { DECODE_IP4_DST_BROADCAST, "(decode) IPV4 packet to broadcast dest address" }, - { DECODE_ICMP4_DST_MULTICAST, "(decode) ICMP4 packet to multicast dest address" }, - { DECODE_ICMP4_DST_BROADCAST, "(decode) ICMP4 packet to broadcast dest address" }, - { DECODE_ICMP4_TYPE_OTHER, "(decode) ICMP4 type other" }, - { DECODE_TCP_BAD_URP, "(decode) TCP urgent pointer exceeds payload length or no payload" }, - { DECODE_TCP_SYN_FIN, "(decode) TCP SYN with FIN" }, - { DECODE_TCP_SYN_RST, "(decode) TCP SYN with RST" }, - { DECODE_TCP_MUST_ACK, "(decode) TCP PDU missing ack for established session" }, - { DECODE_TCP_NO_SYN_ACK_RST, "(decode) TCP has no SYN, ACK, or RST" }, - { DECODE_ETH_HDR_TRUNC, "(decode) truncated eth header" }, - { DECODE_IP4_HDR_TRUNC, "(decode) truncated IP4 header" }, - { DECODE_ICMP4_HDR_TRUNC, "(decode) truncated ICMP4 header" }, - { DECODE_ICMP6_HDR_TRUNC, "(decode) truncated ICMP6 header" }, - { DECODE_IP4_MIN_TTL, "(snort decoder) IPV4 packet below TTL limit" }, - { DECODE_IP6_ZERO_HOP_LIMIT, "(snort decoder) IPV6 packet has zero hop limit" }, - { DECODE_IP4_DF_OFFSET, "(decode) IPV4 packet both DF and offset set" }, - { DECODE_ICMP6_TYPE_OTHER, "(decode) ICMP6 type not decoded" }, - { DECODE_ICMP6_DST_MULTICAST, "(decode) ICMP6 packet to multicast address" }, - { DECODE_TCP_SHAFT_SYNFLOOD, "(decode) DDOS shaft synflood" }, - { DECODE_ICMP_PING_NMAP, "(decode) ICMP PING NMAP" }, - { DECODE_ICMP_ICMPENUM, "(decode) ICMP icmpenum v1.1.1" }, - { DECODE_ICMP_REDIRECT_HOST, "(decode) ICMP redirect host" }, - { DECODE_ICMP_REDIRECT_NET, "(decode) ICMP redirect net" }, - { DECODE_ICMP_TRACEROUTE_IPOPTS, "(decode) ICMP traceroute ipopts" }, - { DECODE_ICMP_SOURCE_QUENCH, "(decode) ICMP Source Quench" }, - { DECODE_ICMP_BROADSCAN_SMURF_SCANNER, "(decode) Broadscan Smurf Scanner" }, - { DECODE_ICMP_DST_UNREACH_ADMIN_PROHIBITED, "(decode) ICMP Destination Unreachable Communication Administratively Prohibited" }, - { DECODE_ICMP_DST_UNREACH_DST_HOST_PROHIBITED, "(decode) ICMP Destination Unreachable Communication with Destination Host is Administratively Prohibited" }, - { DECODE_ICMP_DST_UNREACH_DST_NET_PROHIBITED, "(decode) ICMP Destination Unreachable Communication with Destination Network is Administratively Prohibited" }, - { DECODE_IP_OPTION_SET, "(decode) MISC IP option set" }, - { DECODE_UDP_LARGE_PACKET, "(decode) MISC Large UDP Packet" }, - { DECODE_TCP_PORT_ZERO, "(decode) BAD-TRAFFIC TCP port 0 traffic" }, - { DECODE_UDP_PORT_ZERO, "(decode) BAD-TRAFFIC UDP port 0 traffic" }, - { DECODE_IP_RESERVED_FRAG_BIT, "(decode) BAD-TRAFFIC IP reserved bit set" }, - { DECODE_IP_UNASSIGNED_PROTO, "(decode) BAD-TRAFFIC Unassigned/Reserved IP protocol" }, - { DECODE_IP_BAD_PROTO, "(decode) BAD-TRAFFIC Bad IP protocol" }, - { DECODE_ICMP_PATH_MTU_DOS, "(decode) ICMP PATH MTU denial of service attempt" }, - { DECODE_ICMP_DOS_ATTEMPT, "(decode) BAD-TRAFFIC linux ICMP header dos attempt" }, - { DECODE_IPV6_ISATAP_SPOOF, "(decode) BAD-TRAFFIC ISATAP-addressed IPv6 traffic spoofing attempt" }, - { DECODE_PGM_NAK_OVERFLOW, "(decode) BAD-TRAFFIC PGM nak list overflow attempt" }, - { DECODE_IGMP_OPTIONS_DOS, "(decode) DOS IGMP IP Options validation attempt" }, - { DECODE_IP6_EXCESS_EXT_HDR, "(decode) too many IP6 extension headers" }, - { DECODE_ICMPV6_UNREACHABLE_NON_RFC_4443_CODE, "(decode) ICMPv6 packet of type 1 (destination unreachable) with non-RFC 4443 code" }, - { DECODE_IPV6_BAD_FRAG_PKT, "(decode) bogus fragmentation packet. Possible BSD attack" }, - { DECODE_ZERO_LENGTH_FRAG, "(decode) fragment with zero length" }, - { DECODE_ICMPV6_NODE_INFO_BAD_CODE, "(decode) ICMPv6 node info query/response packet with a code greater than 2" }, - { DECODE_IPV6_ROUTE_ZERO, "(snort decoder) IPV6 routing type 0 extension header" }, - { DECODE_ERSPAN_HDR_VERSION_MISMATCH, "(decode) ERSpan Header version mismatch" }, - { DECODE_ERSPAN2_DGRAM_LT_HDR, "(decode) captured < ERSpan Type2 Header Length" }, - { DECODE_ERSPAN3_DGRAM_LT_HDR, "(decode) captured < ERSpan Type3 Header Length" }, - - { DECODE_BAD_MPLS, "(decode) Bad MPLS Frame" }, - { DECODE_BAD_MPLS_LABEL0, "(decode) MPLS Label 0 Appears in Nonbottom Header" }, - { DECODE_BAD_MPLS_LABEL1, "(decode) MPLS Label 1 Appears in Bottom Header" }, - { DECODE_BAD_MPLS_LABEL2, "(decode) MPLS Label 2 Appears in Nonbottom Header" }, - { DECODE_BAD_MPLS_LABEL3, "(decode) MPLS Label 3 Appears in Header" }, - { DECODE_MPLS_RESERVED_LABEL, "(decode) MPLS Label 4, 5,.. or 15 Appears in Header" }, - { DECODE_MPLS_LABEL_STACK, "(decode) Too Many MPLS headers" }, - - { 0, nullptr } -}; - -//------------------------------------------------------------------------- -// decode module -//------------------------------------------------------------------------- - -DecodeModule::DecodeModule() : - Module("decode", decode_params, decode_rules) { } - -bool DecodeModule::set(const char*, Value& v, SnortConfig* sc) -{ - if ( v.is("decode_data_link") ) - { - if ( v.get_bool() ) - ConfigDecodeDataLink(sc, ""); - } - else if ( v.is("decode_esp") ) - sc->enable_esp = v.get_bool(); - - else if ( v.is("enable_deep_teredo_inspection") ) - sc->enable_teredo = v.get_long(); // FIXIT move to existing bitfield - - else if ( v.is("enable_gtp") ) - { - if ( v.get_bool() ) - sc->enable_gtp = 1; // FIXIT move to existing bitfield - } - else if ( v.is("enable_mpls_multicast") ) - { - if ( v.get_bool() ) - sc->run_flags |= RUN_FLAG__MPLS_MULTICAST; // FIXIT move to existing bitfield - } - else if ( v.is("enable_mpls_overlapping_ip") ) - { - if ( v.get_bool() ) - sc->run_flags |= RUN_FLAG__MPLS_OVERLAPPING_IP; // FIXIT move to existing bitfield - } - else if ( v.is("gtp_ports") ) - ConfigGTPDecoding(sc, v.get_string()); - - else if ( v.is("max_mpls_label_chain_len") ) - sc->mpls_stack_depth = v.get_long(); - - else if ( v.is("mpls_payload_type") ) - sc->mpls_payload_type = v.get_long() + 1; - - else if ( v.is("paf_max") ) - sc->paf_max = v.get_long(); - - else if ( v.is("snaplen") ) - ConfigPacketSnaplen(sc, v.get_string()); - - else - return false; - - return true; -} - diff --git a/src/protocols/decode_module.h b/src/protocols/decode_module.h deleted file mode 100644 index 148a8e38b..000000000 --- a/src/protocols/decode_module.h +++ /dev/null @@ -1,221 +0,0 @@ -/* -** Copyright (C) 2014 Cisco and/or its affiliates. All rights reserved. -** -** This program is free software; you can redistribute it and/or modify -** it under the terms of the GNU General Public License Version 2 as -** published by the Free Software Foundation. You may not use, modify or -** distribute this program under any other version of the GNU General -** Public License. -** -** 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -// decode_module.h author Russ Combs - -#ifndef DECODE_MODULE -#define DECODE_MODULE - -#include "framework/module.h" - -#define GID_DECODE 116 - -#define DECODE_NOT_IPV4_DGRAM 1 -#define DECODE_IPV4_INVALID_HEADER_LEN 2 -#define DECODE_IPV4_DGRAM_LT_IPHDR 3 -#define DECODE_IPV4OPT_BADLEN 4 -#define DECODE_IPV4OPT_TRUNCATED 5 -#define DECODE_IPV4_DGRAM_GT_CAPLEN 6 - -#define DECODE_TCP_DGRAM_LT_TCPHDR 45 -#define DECODE_TCP_INVALID_OFFSET 46 -#define DECODE_TCP_LARGE_OFFSET 47 - -#define DECODE_TCPOPT_BADLEN 54 -#define DECODE_TCPOPT_TRUNCATED 55 -#define DECODE_TCPOPT_TTCP 56 -#define DECODE_TCPOPT_OBSOLETE 57 -#define DECODE_TCPOPT_EXPERIMENTAL 58 -#define DECODE_TCPOPT_WSCALE_INVALID 59 - -#define DECODE_UDP_DGRAM_LT_UDPHDR 95 -#define DECODE_UDP_DGRAM_INVALID_LENGTH 96 -#define DECODE_UDP_DGRAM_SHORT_PACKET 97 -#define DECODE_UDP_DGRAM_LONG_PACKET 98 - -#define DECODE_ICMP_DGRAM_LT_ICMPHDR 105 -#define DECODE_ICMP_DGRAM_LT_TIMESTAMPHDR 106 -#define DECODE_ICMP_DGRAM_LT_ADDRHDR 107 - -#define DECODE_ARP_TRUNCATED 109 -#define DECODE_EAPOL_TRUNCATED 110 -#define DECODE_EAPKEY_TRUNCATED 111 -#define DECODE_EAP_TRUNCATED 112 - -#define DECODE_BAD_PPPOE 120 -#define DECODE_BAD_VLAN 130 -#define DECODE_BAD_VLAN_ETHLLC 131 -#define DECODE_BAD_VLAN_OTHER 132 -#define DECODE_BAD_80211_ETHLLC 133 -#define DECODE_BAD_80211_OTHER 134 - -#define DECODE_BAD_TRH 140 -#define DECODE_BAD_TR_ETHLLC 141 -#define DECODE_BAD_TR_MR_LEN 142 -#define DECODE_BAD_TRHMR 143 - -#define DECODE_BAD_TRAFFIC_LOOPBACK 150 -#define DECODE_BAD_TRAFFIC_SAME_SRCDST 151 - -#define DECODE_GRE_DGRAM_LT_GREHDR 160 -#define DECODE_GRE_MULTIPLE_ENCAPSULATION 161 -#define DECODE_GRE_INVALID_VERSION 162 -#define DECODE_GRE_INVALID_HEADER 163 -#define DECODE_GRE_V1_INVALID_HEADER 164 -#define DECODE_GRE_TRANS_DGRAM_LT_TRANSHDR 165 - -#define DECODE_BAD_MPLS 170 -#define DECODE_BAD_MPLS_LABEL0 171 -#define DECODE_BAD_MPLS_LABEL1 172 -#define DECODE_BAD_MPLS_LABEL2 173 -#define DECODE_BAD_MPLS_LABEL3 174 -#define DECODE_MPLS_RESERVED_LABEL 175 -#define DECODE_MPLS_LABEL_STACK 176 - -#define DECODE_ICMP_ORIG_IP_TRUNCATED 250 -#define DECODE_ICMP_ORIG_IP_VER_MISMATCH 251 -#define DECODE_ICMP_ORIG_DGRAM_LT_ORIG_IP 252 -#define DECODE_ICMP_ORIG_PAYLOAD_LT_64 253 -#define DECODE_ICMP_ORIG_PAYLOAD_GT_576 254 -#define DECODE_ICMP_ORIG_IP_WITH_FRAGOFFSET 255 - -#define DECODE_IPV6_MIN_TTL 270 -#define DECODE_IPV6_IS_NOT 271 -#define DECODE_IPV6_TRUNCATED_EXT 272 -#define DECODE_IPV6_TRUNCATED 273 -#define DECODE_IPV6_DGRAM_LT_IPHDR 274 -#define DECODE_IPV6_DGRAM_GT_CAPLEN 275 -#define DECODE_IPV6_DST_ZERO 276 -#define DECODE_IPV6_SRC_MULTICAST 277 -#define DECODE_IPV6_DST_RESERVED_MULTICAST 278 -#define DECODE_IPV6_BAD_OPT_TYPE 279 -#define DECODE_IPV6_BAD_MULTICAST_SCOPE 280 -#define DECODE_IPV6_BAD_NEXT_HEADER 281 -#define DECODE_IPV6_ROUTE_AND_HOPBYHOP 282 -#define DECODE_IPV6_TWO_ROUTE_HEADERS 283 - -#define DECODE_ICMPV6_TOO_BIG_BAD_MTU 285 -#define DECODE_ICMPV6_UNREACHABLE_NON_RFC_2463_CODE 286 -#define DECODE_ICMPV6_SOLICITATION_BAD_CODE 287 -#define DECODE_ICMPV6_ADVERT_BAD_CODE 288 -#define DECODE_ICMPV6_SOLICITATION_BAD_RESERVED 289 -#define DECODE_ICMPV6_ADVERT_BAD_REACHABLE 290 - -#define DECODE_IPV6_TUNNELED_IPV4_TRUNCATED 291 -#define DECODE_IPV6_DSTOPTS_WITH_ROUTING 292 -#define DECODE_IP_MULTIPLE_ENCAPSULATION 293 - -#define DECODE_ESP_HEADER_TRUNC 294 -#define DECODE_IPV6_BAD_OPT_LEN 295 -#define DECODE_IPV6_UNORDERED_EXTENSIONS 296 - -#define DECODE_GTP_MULTIPLE_ENCAPSULATION 297 -#define DECODE_GTP_BAD_LEN 298 - -//----------------------------------------------------- -// remember to add rules to preproc_rules/decoder.rules -// add the new decoder rules to the following enum. - -#define DECODE_START_INDEX 400 - -enum { - DECODE_TCP_XMAS = DECODE_START_INDEX, - DECODE_TCP_NMAP_XMAS, - DECODE_DOS_NAPTHA, - DECODE_SYN_TO_MULTICAST, - DECODE_ZERO_TTL, - DECODE_BAD_FRAGBITS, - DECODE_UDP_IPV6_ZERO_CHECKSUM, - DECODE_IP4_LEN_OFFSET, - DECODE_IP4_SRC_THIS_NET, - DECODE_IP4_DST_THIS_NET, - DECODE_IP4_SRC_MULTICAST, - DECODE_IP4_SRC_RESERVED, - DECODE_IP4_DST_RESERVED, - DECODE_IP4_SRC_BROADCAST, - DECODE_IP4_DST_BROADCAST, - DECODE_ICMP4_DST_MULTICAST, - DECODE_ICMP4_DST_BROADCAST, - DECODE_ICMP4_TYPE_OTHER = 418, - DECODE_TCP_BAD_URP, - DECODE_TCP_SYN_FIN, - DECODE_TCP_SYN_RST, - DECODE_TCP_MUST_ACK, - DECODE_TCP_NO_SYN_ACK_RST, - DECODE_ETH_HDR_TRUNC, - DECODE_IP4_HDR_TRUNC, - DECODE_ICMP4_HDR_TRUNC, - DECODE_ICMP6_HDR_TRUNC, - DECODE_IP4_MIN_TTL, - DECODE_IP6_ZERO_HOP_LIMIT, - DECODE_IP4_DF_OFFSET, - DECODE_ICMP6_TYPE_OTHER, - DECODE_ICMP6_DST_MULTICAST, - DECODE_TCP_SHAFT_SYNFLOOD, - DECODE_ICMP_PING_NMAP, - DECODE_ICMP_ICMPENUM, - DECODE_ICMP_REDIRECT_HOST, - DECODE_ICMP_REDIRECT_NET, - DECODE_ICMP_TRACEROUTE_IPOPTS, - DECODE_ICMP_SOURCE_QUENCH, - DECODE_ICMP_BROADSCAN_SMURF_SCANNER, - DECODE_ICMP_DST_UNREACH_ADMIN_PROHIBITED, - DECODE_ICMP_DST_UNREACH_DST_HOST_PROHIBITED, - DECODE_ICMP_DST_UNREACH_DST_NET_PROHIBITED, - DECODE_IP_OPTION_SET, - DECODE_UDP_LARGE_PACKET, - DECODE_TCP_PORT_ZERO, - DECODE_UDP_PORT_ZERO, - DECODE_IP_RESERVED_FRAG_BIT, - DECODE_IP_UNASSIGNED_PROTO, - DECODE_IP_BAD_PROTO, - DECODE_ICMP_PATH_MTU_DOS, - DECODE_ICMP_DOS_ATTEMPT, - DECODE_IPV6_ISATAP_SPOOF, - DECODE_PGM_NAK_OVERFLOW, - DECODE_IGMP_OPTIONS_DOS, - DECODE_IP6_EXCESS_EXT_HDR, - DECODE_ICMPV6_UNREACHABLE_NON_RFC_4443_CODE, - DECODE_IPV6_BAD_FRAG_PKT, - DECODE_ZERO_LENGTH_FRAG, - DECODE_ICMPV6_NODE_INFO_BAD_CODE, - DECODE_IPV6_ROUTE_ZERO, - DECODE_ERSPAN_HDR_VERSION_MISMATCH, - DECODE_ERSPAN2_DGRAM_LT_HDR, - DECODE_ERSPAN3_DGRAM_LT_HDR, - DECODE_INDEX_MAX -}; - - -//------------------------------------------------------------------------- -// module -//------------------------------------------------------------------------- - -class DecodeModule : public Module -{ -public: - DecodeModule(); - bool set(const char*, Value&, SnortConfig*); - - unsigned get_gid() const - { return GID_DECODE; }; -}; - -#endif - diff --git a/src/protocols/encode.cc b/src/protocols/encode.cc deleted file mode 100644 index bc09dad72..000000000 --- a/src/protocols/encode.cc +++ /dev/null @@ -1,1528 +0,0 @@ -/**************************************************************************** - * -** Copyright (C) 2014 Cisco and/or its affiliates. All rights reserved. - * Copyright (C) 2005-2013 Sourcefire, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License Version 2 as - * published by the Free Software Foundation. You may not use, modify or - * distribute this program under any other version of the GNU General - * Public License. - * - * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - ****************************************************************************/ - -// @file encode.c -// @author Russ Combs - -#include "encode.h" - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include -#ifdef HAVE_DUMBNET_H -#include -#else -#include -#endif - -#include "assert.h" -#include "packet_io/sfdaq.h" -#include "sf_iph.h" -#include "snort.h" -#include "stream5/stream_api.h" -#include "checksum.h" - -#define GET_IP_HDR_LEN(h) (((h)->ip_verhl & 0x0f) << 2) -#define GET_TCP_HDR_LEN(h) (((h)->th_offx2 & 0xf0) >> 2) -#define SET_TCP_HDR_LEN(h, n) (h)->th_offx2 = ((n << 2) & 0xF0) - -#define MIN_TTL 64 -#define MAX_TTL 255 - -#define ICMP_UNREACH_DATA 8 // (per RFC 792) -#define IP_ID_COUNT 8192 - -static THREAD_LOCAL uint8_t* dst_mac = NULL; -Packet* encode_pkt = NULL; -uint64_t total_rebuilt_pkts = 0; - -static inline int IsIcmp (int type) -{ - static constexpr int s_icmp[ENC_MAX] = { 0, 0, 1, 1, 1 }; - return ( s_icmp[type] ); -} - -//------------------------------------------------------------------------- -// encoders operate layer by layer: -// * base+off is start of packet -// * base+end is start of current layer -// * base+size-1 is last byte of packet (in) / buffer (out) -typedef blob_t Buffer; - -typedef enum { - ENC_OK, ENC_BAD_PROTO, ENC_BAD_OPT, ENC_OVERFLOW -} ENC_STATUS; - -typedef struct { - EncodeType type; - EncodeFlags flags; - - uint8_t layer; - const Packet* p; - uint16_t ip_len; - uint8_t* ip_hdr; - - const uint8_t* payLoad; - uint32_t payLen; - uint8_t proto; - -} EncState; - -#define FORWARD(e) (e->flags & ENC_FLAG_FWD) -#define REVERSE(f) (!(f & ENC_FLAG_FWD)) - -// PKT_MAX is sized to ensure that any reassembled packet -// can accommodate a full datagram at innermost layer -#define PKT_MAX (ETHERNET_HEADER_LEN + VLAN_HEADER_LEN + ETHERNET_MTU + IP_MAXPACKET) - -// all layer encoders look like this: -typedef ENC_STATUS (*Encoder)(EncState*, Buffer* in, Buffer* out); -typedef ENC_STATUS (*Updater)(Packet*, Layer*, uint32_t* len); -typedef void (*Formatter)(EncodeFlags, const Packet* p, Packet* c, Layer*); -// TBD implement other encoder functions - -typedef struct { - Encoder fencode; - Updater fupdate; - Formatter fformat; -} EncoderFunctions; - -// forward declaration; definition at end of file -// the alternative is to put all the function declarations -// here followed by the static array definition. -extern EncoderFunctions encoders[PROTO_MAX]; - -static void IpId_Init(); -static void IpId_Term(); - -static const uint8_t* Encode_Packet( - EncState* enc, const Packet* p, uint32_t* len); - -static ENC_STATUS UN6_Encode(EncState*, Buffer*, Buffer*); - -//------------------------------------------------------------------------- - -static inline PROTO_ID NextEncoder (EncState* enc) -{ - if ( enc->layer < enc->p->next_layer ) - { - PROTO_ID next = enc->p->layers[enc->layer++].proto; - if ( next < PROTO_MAX ) - { - if ( encoders[next].fencode ) return next; - } - } - return PROTO_MAX; -} - -//------------------------------------------------------------------------- -// basic setup stuff -//------------------------------------------------------------------------- - -void Encode_Init (void) -{ - IpId_Init(); -} - -void Encode_Term (void) -{ - IpId_Term(); -} - -//------------------------------------------------------------------------- -// encoders: -// - raw pkt data only, no need for Packet stuff except to facilitate -// encoding -// - don't include original options -// - inner layer differs from original (eg tcp data segment becomes rst) -// - must ensure proper ttl/hop limit for reverse direction -// - sparc twiddle must be factored in packet start for transmission -// -// iterate over decoded layers and encode the response packet. actually -// make nested calls. on the way in we setup invariant stuff and as we -// unwind the stack we finish up encoding in a more normal fashion (now -// the outer layer knows the length of the inner layer, etc.). -// -// when multiple responses are sent, both forwards and backwards directions, -// or multiple ICMP types (unreachable port, host, net), it may be possible -// to reuse the 1st encoding and just tweak it. optimization for later -// consideration. - -// pci is copied from in to out -// * addresses / ports are swapped if !fwd -// * options, etc. are stripped -// * checksums etc. are set -// * if next layer is udp, it is set to icmp unreachable w/udp -// * if next layer is tcp, it becomes a tcp rst or tcp fin w/opt data -//------------------------------------------------------------------------- - -SO_PUBLIC const uint8_t* Encode_Reject( - EncodeType type, EncodeFlags flags, const Packet* p, uint32_t* len) -{ - EncState enc; - - enc.type = type; - enc.flags = flags; - - enc.payLoad = NULL; - enc.payLen = 0; - - enc.ip_hdr = NULL; - enc.ip_len = 0; - enc.proto = 0; - - if ( encode_pkt ) - p = encode_pkt; - - return Encode_Packet(&enc, p, len); -} - -SO_PUBLIC const uint8_t* Encode_Response( - EncodeType type, EncodeFlags flags, const Packet* p, uint32_t* len, - const uint8_t* payLoad, uint32_t payLen -) { - EncState enc; - - enc.type = type; - enc.flags = flags; - - enc.payLoad = payLoad; - enc.payLen = payLen; - - enc.ip_hdr = NULL; - enc.ip_len = 0; - enc.proto = 0; - - if ( encode_pkt ) - p = encode_pkt; - - return Encode_Packet(&enc, p, len); -} - -//------------------------------------------------------------------------- -// formatters: -// - these packets undergo detection -// - need to set Packet stuff except for frag3 which calls grinder -// - include original options except for frag3 inner ip -// - inner layer header is very similar but payload differs -// - original ttl is always used -//------------------------------------------------------------------------- -#ifdef HAVE_DAQ_ADDRESS_SPACE_ID -SO_PUBLIC int Encode_Format_With_DAQ_Info ( - EncodeFlags f, const Packet* p, Packet* c, PseudoPacketType type, - const DAQ_PktHdr_t* phdr, uint32_t opaque) - -#elif defined(HAVE_DAQ_ACQUIRE_WITH_META) -SO_PUBLIC int Encode_Format_With_DAQ_Info ( - EncodeFlags f, const Packet* p, Packet* c, PseudoPacketType type, - uint32_t opaque) -#else -SO_PUBLIC int Encode_Format (EncodeFlags f, const Packet* p, Packet* c, PseudoPacketType type) -#endif -{ - DAQ_PktHdr_t* pkth = (DAQ_PktHdr_t*)c->pkth; - uint8_t* pkt = (uint8_t*)c->pkt; - - int i, next_layer = p->next_layer; - Layer* lyr; - size_t len; - - if ( next_layer < 1 ) return -1; - - memset(c, 0, PKT_ZERO_LEN); - c->raw_ip6h = NULL; - - c->pkth = pkth; - c->pkt = pkt; - -#ifdef HAVE_DAQ_ADDRESS_SPACE_ID - pkth->ingress_index = phdr->ingress_index; - pkth->ingress_group = phdr->ingress_group; - pkth->egress_index = phdr->egress_index; - pkth->egress_group = phdr->egress_group; - pkth->flags = phdr->flags & (~DAQ_PKT_FLAG_HW_TCP_CS_GOOD); - pkth->address_space_id = phdr->address_space_id; - pkth->opaque = opaque; -#elif defined(HAVE_DAQ_ACQUIRE_WITH_META) - pkth->opaque = opaque; -#endif - - if ( f & ENC_FLAG_NET ) - { - for ( i = next_layer-1; i >= 0; i-- ) - if ( p->layers[i].proto == PROTO_IP4 - || p->layers[i].proto == PROTO_IP6 - ) - break; - if ( i < next_layer ) next_layer = i + 1; - } - // copy raw packet data to clone - lyr = (Layer*)p->layers + next_layer - 1; - len = lyr->start - p->pkt + lyr->length; - - memcpy((void*)c->pkt, p->pkt, len); - - // set up layers - for ( i = 0; i < next_layer; i++ ) - { - const uint8_t* b = c->pkt + (p->layers[i].start - p->pkt); - lyr = c->layers + i; - - lyr->proto = p->layers[i].proto; - lyr->length = p->layers[i].length; - lyr->start = (uint8_t*)b; - - if ( lyr->proto < PROTO_MAX ) - encoders[lyr->proto].fformat(f, p, c, lyr); - -#ifdef DEBUG - else - FatalError("Encode_New() => unsupported proto = %d\n", - lyr->proto); -#endif - } - c->next_layer = next_layer; - - // setup payload info - c->data = lyr->start + lyr->length; - len = c->data - c->pkt; - assert(len < PKT_MAX - IP_MAXPACKET); - c->max_dsize = IP_MAXPACKET - len; - - c->proto_bits = p->proto_bits; - c->packet_flags |= PKT_PSEUDO; - c->pseudo_type = type; - UpdateRebuiltPktCount(); - - switch ( type ) - { - case PSEUDO_PKT_SMB_SEG: - case PSEUDO_PKT_DCE_SEG: - case PSEUDO_PKT_DCE_FRAG: - case PSEUDO_PKT_SMB_TRANS: - c->packet_flags |= PKT_REASSEMBLED_OLD; - break; - default: - break; - } - - // setup pkt capture header - pkth->caplen = pkth->pktlen = len; - pkth->ts = p->pkth->ts; - - // cooked packet gets same policy as raw - c->user_policy_id = p->user_policy_id; - - if ( !c->max_dsize ) - return -1; - - return 0; -} - -//------------------------------------------------------------------------- -// formatters: -// - these packets undergo detection -// - need to set Packet stuff except for frag3 which calls grinder -// - include original options except for frag3 inner ip -// - inner layer header is very similar but payload differs -// - original ttl is always used -//------------------------------------------------------------------------- - -#ifdef HAVE_DAQ_ADDRESS_SPACE_ID -SO_PUBLIC int Encode_Format (EncodeFlags f, const Packet* p, Packet* c, PseudoPacketType type) -{ - return Encode_Format_With_DAQ_Info(f, p, c, type, p->pkth, p->pkth->opaque); -} -#elif defined(HAVE_DAQ_ACQUIRE_WITH_META) -SO_PUBLIC int Encode_Format (EncodeFlags f, const Packet* p, Packet* c, PseudoPacketType type) -{ - return Encode_Format_With_DAQ_Info(f, p, c, type, p->pkth->opaque); -} -#endif - -//------------------------------------------------------------------------- -// updaters: these functions set length and checksum fields, only needed -// when a packet is modified. some packets only have replacements so only -// the checksums need to be updated. we always set the length rather than -// checking each time if needed. -//------------------------------------------------------------------------- - -SO_PUBLIC void Encode_Update (Packet* p) -{ - int i; - uint32_t len = 0; - DAQ_PktHdr_t* pkth = (DAQ_PktHdr_t*)p->pkth; - - p->actual_ip_len = 0; - - for ( i = p->next_layer - 1; i >= 0; i-- ) - { - Layer* lyr = p->layers + i; - encoders[lyr->proto].fupdate(p, lyr, &len); - } - // see IP6_Update() for an explanation of this ... - if ( !(p->packet_flags & PKT_MODIFIED) - || (p->packet_flags & PKT_RESIZED) - ) - pkth->caplen = pkth->pktlen = len; - - p->packet_flags &= ~PKT_LOGGED; -} - -//------------------------------------------------------------------------- -// internal packet support -//------------------------------------------------------------------------- - -SO_PUBLIC Packet* Encode_New () -{ - Packet* p = (Packet*)SnortAlloc(sizeof(*p)); - uint8_t* b = (uint8_t*)SnortAlloc(sizeof(*p->pkth) + PKT_MAX + SPARC_TWIDDLE); - - if ( !p || !b ) - FatalError("Encode_New() => Failed to allocate packet\n"); - - p->pkth = (DAQ_PktHdr_t*)b; - b += sizeof(*p->pkth); - b += SPARC_TWIDDLE; - p->pkt = b; - - return p; -} - -SO_PUBLIC void Encode_Delete (Packet* p) -{ - free((void*)p->pkth); // cast away const! - free(p); -} - -/* Set the destination MAC address*/ -SO_PUBLIC void Encode_SetDstMAC(uint8_t *mac) -{ - dst_mac = mac; -} -//------------------------------------------------------------------------- -// private implementation stuff -//------------------------------------------------------------------------- - -static THREAD_LOCAL uint8_t s_pkt[PKT_MAX]; - -static const uint8_t* Encode_Packet( - EncState* enc, const Packet* p, uint32_t* len) -{ - Buffer ibuf, obuf; - ENC_STATUS status = ENC_BAD_PROTO; - PROTO_ID next; - - ibuf.base = (uint8_t*)p->pkt; - ibuf.off = ibuf.end = 0; - ibuf.size = p->pkth->caplen; - - obuf.base = s_pkt; - obuf.off = obuf.end = 0; - obuf.size = sizeof(s_pkt); - - enc->layer = 0; - enc->p = p; - - next = NextEncoder(enc); - - if ( next < PROTO_MAX ) - { - Encoder e = encoders[next].fencode; - status = (*e)(enc, &ibuf, &obuf); - } - if ( status != ENC_OK || enc->layer != p->next_layer ) - { - *len = 0; - return NULL; - } - *len = (uint32_t)obuf.end; - return obuf.base + obuf.off; -} - -//------------------------------------------------------------------------- -// ip id considerations: -// -// we use dnet's rand services to generate a vector of random 16-bit values and -// iterate over the vector as IDs are assigned. when we wrap to the beginning, -// the vector is randomly reordered. -//------------------------------------------------------------------------- - -static THREAD_LOCAL rand_t* s_rand = NULL; -static THREAD_LOCAL uint16_t s_id_index = 0; -static THREAD_LOCAL uint16_t s_id_pool[IP_ID_COUNT]; - -static void IpId_Init (void) -{ -#ifndef VALGRIND_TESTING - if ( s_rand ) rand_close(s_rand); - - // rand_open() can yield valgriind errors because the - // starting seed may come from "random stack contents" - // (see man 3 dnet) - s_rand = rand_open(); - - if ( !s_rand ) - FatalError("encode::IpId_Init: rand_open() failed.\n"); - - rand_get(s_rand, s_id_pool, sizeof(s_id_pool)); -#endif -} - -static void IpId_Term (void) -{ - if ( s_rand ) rand_close(s_rand); - s_rand = NULL; -} - -static inline uint16_t IpId_Next () -{ -#if defined(REG_TEST) || defined(VALGRIND_TESTING) - uint16_t id = htons(s_id_index + 1); -#else - uint16_t id = s_id_pool[s_id_index]; -#endif - s_id_index = (s_id_index + 1) % IP_ID_COUNT; - -#ifndef VALGRIND_TESTING - if ( !s_id_index ) - rand_shuffle(s_rand, s_id_pool, sizeof(s_id_pool), 1); -#endif - return id; -} - -//------------------------------------------------------------------------- -// ttl considerations: -// -// we try to use the TTL captured for the session by the stream preprocessor -// when the session started. if that is not available, we use the current -// TTL for forward packets and use (maximum - current) TTL for reverse -// packets. -// -// the reason we don't just force ttl to 255 (max) is to make it look a -// little more authentic. -// -// for reference, flexresp used a const rand >= 64 in both directions (the -// number was determined at startup and never changed); flexresp2 used the -// next higher multiple of 64 in both directions; and react used a const -// 64 in both directions. -// -// note that the ip6 hop limit field is entirely equivalent to the ip4 TTL. -// hop limit is in fact a more accurrate name for the actual usage of this -// field. -//------------------------------------------------------------------------- - -static inline uint8_t GetTTL (const EncState* enc) -{ - char dir; - uint8_t ttl; - int outer = !enc->ip_hdr; - - if ( !enc->p->flow ) - return 0; - - if ( enc->p->packet_flags & PKT_FROM_CLIENT ) - dir = FORWARD(enc) ? SSN_DIR_CLIENT : SSN_DIR_SERVER; - else - dir = FORWARD(enc) ? SSN_DIR_SERVER : SSN_DIR_CLIENT; - - // outermost ip is considered to be outer here, - // even if it is the only ip layer ... - ttl = stream.get_session_ttl(enc->p->flow, dir, outer); - - // so if we don't get outer, we use inner - if ( 0 == ttl && outer ) - ttl = stream.get_session_ttl(enc->p->flow, dir, 0); - - return ttl; -} - -static inline uint8_t FwdTTL (const EncState* enc, uint8_t ttl) -{ - uint8_t new_ttl = GetTTL(enc); - if ( !new_ttl ) - new_ttl = ttl; - return new_ttl; -} - -static inline uint8_t RevTTL (const EncState* enc, uint8_t ttl) -{ - uint8_t new_ttl = GetTTL(enc); - if ( !new_ttl ) - new_ttl = ( MAX_TTL - ttl ); - if ( new_ttl < MIN_TTL ) - new_ttl = MIN_TTL; - return new_ttl; -} - -//------------------------------------------------------------------------- -// the if in UPDATE_BOUND can be defined out after testing because: -// 1. the packet was already decoded in decode.c so is structurally sound; and -// 2. encode takes at most the same space as decode. -#define UPDATE_BOUND(buf, n) \ - buf->end += n; \ - if ( buf->end > buf->size ) \ - return ENC_OVERFLOW -//------------------------------------------------------------------------- -// BUFLEN -// Get the buffer length for a given protocol -#define BUFF_DIFF(buf, ho) ((uint8_t*)(buf->base+buf->end)-(uint8_t*)ho) - -//------------------------------------------------------------------------- -// ethernet -//------------------------------------------------------------------------- - -static ENC_STATUS Eth_Encode (EncState* enc, Buffer* in, Buffer* out) -{ - // not raw ip -> encode layer 2 - int raw = ( enc->flags & ENC_FLAG_RAW ); - - EtherHdr* hi = (EtherHdr*)enc->p->layers[enc->layer-1].start; - PROTO_ID next = NextEncoder(enc); - - // if not raw ip AND out buf is empty - if ( !raw && (out->off == out->end) ) - { - // for alignment - out->off = out->end = SPARC_TWIDDLE; - } - // if not raw ip OR out buf is not empty - if ( !raw || (out->off != out->end) ) - { - // we get here for outer-most layer when not raw ip - // we also get here for any encapsulated ethernet layer. - EtherHdr* ho = (EtherHdr*)(out->base + out->end); - UPDATE_BOUND(out, sizeof(*ho)); - - ho->ether_type = hi->ether_type; - if ( FORWARD(enc) ) - { - memcpy(ho->ether_src, hi->ether_src, sizeof(ho->ether_src)); - /*If user configured remote MAC address, use it*/ - if (NULL != dst_mac) - memcpy(ho->ether_dst, dst_mac, sizeof(ho->ether_dst)); - else - memcpy(ho->ether_dst, hi->ether_dst, sizeof(ho->ether_dst)); - } - else - { - memcpy(ho->ether_src, hi->ether_dst, sizeof(ho->ether_src)); - /*If user configured remote MAC address, use it*/ - if (NULL != dst_mac) - memcpy(ho->ether_dst, dst_mac, sizeof(ho->ether_dst)); - else - memcpy(ho->ether_dst, hi->ether_src, sizeof(ho->ether_dst)); - } - } - if ( next < PROTO_MAX ) - return encoders[next].fencode(enc, in, out); - - return ENC_OK; -} - -static ENC_STATUS Eth_Update (Packet*, Layer* lyr, uint32_t* len) -{ - *len += lyr->length; - return ENC_OK; -} - -static void Eth_Format (EncodeFlags f, const Packet* p, Packet* c, Layer* lyr) -{ - EtherHdr* ch = (EtherHdr*)lyr->start; - c->eh = ch; - - if ( REVERSE(f) ) - { - int i = lyr - c->layers; - EtherHdr* ph = (EtherHdr*)p->layers[i].start; - - memcpy(ch->ether_dst, ph->ether_src, sizeof(ch->ether_dst)); - memcpy(ch->ether_src, ph->ether_dst, sizeof(ch->ether_src)); - } -} - -//------------------------------------------------------------------------- -// VLAN -//------------------------------------------------------------------------- - -static void VLAN_Format (EncodeFlags, const Packet*, Packet* c, Layer* lyr) -{ - c->vh = (VlanTagHdr*)lyr->start; -} - -//------------------------------------------------------------------------- -// GRE -//------------------------------------------------------------------------- -static void GRE_Format (EncodeFlags, const Packet*, Packet* c, Layer* lyr) -{ - c->greh = (GREHdr*)lyr->start; -} - -//------------------------------------------------------------------------- -// IP4 -//------------------------------------------------------------------------- - -static ENC_STATUS IP4_Encode (EncState* enc, Buffer* in, Buffer* out) -{ - int len; - uint32_t start = out->end; - - IPHdr* hi = (IPHdr*)enc->p->layers[enc->layer-1].start; - IPHdr* ho = (IPHdr*)(out->base + out->end); - PROTO_ID next = NextEncoder(enc); - UPDATE_BOUND(out, sizeof(*ho)); - - /* IPv4 encoded header is hardcoded 20 bytes */ - ho->ip_verhl = 0x45; - ho->ip_off = 0; - - ho->ip_id = IpId_Next(); - ho->ip_tos = hi->ip_tos; - ho->ip_proto = hi->ip_proto; - - if ( FORWARD(enc) ) - { - ho->ip_src.s_addr = hi->ip_src.s_addr; - ho->ip_dst.s_addr = hi->ip_dst.s_addr; - - ho->ip_ttl = FwdTTL(enc, hi->ip_ttl); - } - else - { - ho->ip_src.s_addr = hi->ip_dst.s_addr; - ho->ip_dst.s_addr = hi->ip_src.s_addr; - - ho->ip_ttl = RevTTL(enc, hi->ip_ttl); - } - - enc->ip_hdr = (uint8_t*)hi; - enc->ip_len = IP_HLEN(hi) << 2; - - if ( next < PROTO_MAX ) - { - ENC_STATUS err = encoders[next].fencode(enc, in, out); - if ( ENC_OK != err ) return err; - } - if ( enc->proto ) - { - ho->ip_proto = enc->proto; - enc->proto = 0; - } - - len = out->end - start; - ho->ip_len = htons((uint16_t)len); - - ho->ip_csum = 0; - - /* IPv4 encoded header is hardcoded 20 bytes, we save some - * cycles and use the literal header size for checksum */ - ho->ip_csum = in_chksum_ip((uint16_t *)ho, sizeof *ho); - - return ENC_OK; -} - -static ENC_STATUS IP4_Update (Packet* p, Layer* lyr, uint32_t* len) -{ - IPHdr* h = (IPHdr*)(lyr->start); - int i = lyr - p->layers; - - *len += GET_IP_HDR_LEN(h); - - if ( i + 1 == p->next_layer ) - { - *len += p->dsize; - } - h->ip_len = htons((uint16_t)*len); - - if ( !PacketWasCooked(p) || (p->packet_flags & PKT_REBUILT_FRAG) ) - { - h->ip_csum = 0; - h->ip_csum = in_chksum_ip((uint16_t *)h, GET_IP_HDR_LEN(h)); - } - - return ENC_OK; -} - -static void IP4_Format (EncodeFlags f, const Packet* p, Packet* c, Layer* lyr) -{ - // TBD handle nested ip layers - IPHdr* ch = (IPHdr*)lyr->start; - c->iph = ch; - - if ( REVERSE(f) ) - { - int i = lyr - c->layers; - IPHdr* ph = (IPHdr*)p->layers[i].start; - - ch->ip_src.s_addr = ph->ip_dst.s_addr; - ch->ip_dst.s_addr = ph->ip_src.s_addr; - } - if ( f & ENC_FLAG_DEF ) - { - int i = lyr - c->layers; - if ( i + 1 == p->next_layer ) - { - lyr->length = sizeof(*ch); - ch->ip_len = htons(lyr->length); - SET_IP_HLEN(ch, lyr->length >> 2); - } - } - sfiph_build(c, c->iph, AF_INET); -} - -//------------------------------------------------------------------------- -// ICMP -// UNR encoder creates ICMP unreachable -//------------------------------------------------------------------------- - -static inline int IcmpCode (EncodeType et) { - switch ( et ) { - case ENC_UNR_NET: return ICMP_UNREACH_NET; - case ENC_UNR_HOST: return ICMP_UNREACH_HOST; - case ENC_UNR_PORT: return ICMP_UNREACH_PORT; - case ENC_UNR_FW: return ICMP_UNREACH_FILTER_PROHIB; - default: break; - } - return ICMP_UNREACH_PORT; -} - -typedef struct { - uint8_t type; - uint8_t code; - uint16_t cksum; - uint32_t unused; -} IcmpHdr; - -static ENC_STATUS UN4_Encode (EncState* enc, Buffer*, Buffer* out) -{ - uint8_t* p; - - uint8_t* hi = enc->p->layers[enc->layer-1].start; - IcmpHdr* ho = (IcmpHdr*)(out->base + out->end); - -#ifdef DEBUG - if ( enc->type < ENC_UNR_NET ) - return ENC_BAD_OPT; -#endif - - enc->proto = IPPROTO_ICMP; - - UPDATE_BOUND(out, sizeof(*ho)); - ho->type = ICMP_UNREACH; - ho->code = IcmpCode(enc->type); - ho->cksum = 0; - ho->unused = 0; - - // copy original ip header - p = out->base + out->end; - UPDATE_BOUND(out, enc->ip_len); - memcpy(p, enc->ip_hdr, enc->ip_len); - - // copy first 8 octets of original ip data (ie udp header) - p = out->base + out->end; - UPDATE_BOUND(out, ICMP_UNREACH_DATA); - memcpy(p, hi, ICMP_UNREACH_DATA); - - ho->cksum = in_chksum_icmp((uint16_t *)ho, BUFF_DIFF(out, ho)); - - return ENC_OK; -} - -static ENC_STATUS ICMP4_Update (Packet* p, Layer* lyr, uint32_t* len) -{ - IcmpHdr* h = (IcmpHdr*)(lyr->start); - - *len += sizeof(*h) + p->dsize; - - - if ( !PacketWasCooked(p) || (p->packet_flags & PKT_REBUILT_FRAG) ) { - h->cksum = 0; - h->cksum = in_chksum_icmp((uint16_t *)h, *len); - } - - return ENC_OK; -} - -static void ICMP4_Format (EncodeFlags, const Packet*, Packet* c, Layer* lyr) -{ - // TBD handle nested icmp4 layers - c->icmph = (ICMPHdr*)lyr->start; -} - -//------------------------------------------------------------------------- -// UDP -//------------------------------------------------------------------------- - -static ENC_STATUS UDP_Encode (EncState* enc, Buffer* in, Buffer* out) -{ - PROTO_ID next = PROTO_MAX; - - if ( enc->layer < enc->p->next_layer ) - { - next = enc->p->layers[enc->layer].proto; - } - if ((PROTO_GTP == next) && (encoders[next].fencode)) - { - int len; - ENC_STATUS err; - uint32_t start = out->end; - - UDPHdr* hi = (UDPHdr*)enc->p->layers[enc->layer-1].start; - UDPHdr* ho = (UDPHdr*)(out->base + out->end); - UPDATE_BOUND(out, sizeof(*ho)); - - if ( FORWARD(enc) ) - { - ho->uh_sport = hi->uh_sport; - ho->uh_dport = hi->uh_dport; - } - else - { - ho->uh_sport = hi->uh_dport; - ho->uh_dport = hi->uh_sport; - } - - next = NextEncoder(enc); - err = encoders[next].fencode(enc, in, out); - if (ENC_OK != err ) return err; - len = out->end - start; - ho->uh_len = htons((uint16_t)len); - - ho->uh_chk = 0; - - if (IP_VER((IPHdr *)enc->ip_hdr) == 4) { - pseudoheader ps; - ps.sip = ((IPHdr *)enc->ip_hdr)->ip_src.s_addr; - ps.dip = ((IPHdr *)enc->ip_hdr)->ip_dst.s_addr; - ps.zero = 0; - ps.protocol = IPPROTO_UDP; - ps.len = ho->uh_len; - ho->uh_chk = in_chksum_udp(&ps, (uint16_t *)ho, len); - } - else { - pseudoheader6 ps6; - memcpy(ps6.sip, ((IP6RawHdr *)enc->ip_hdr)->ip6_src.s6_addr, sizeof(ps6.sip)); - memcpy(ps6.dip, ((IP6RawHdr *)enc->ip_hdr)->ip6_dst.s6_addr, sizeof(ps6.dip)); - ps6.zero = 0; - ps6.protocol = IPPROTO_UDP; - ps6.len = ho->uh_len; - ho->uh_chk = in_chksum_udp6(&ps6, (uint16_t *)ho, len); - } - - return ENC_OK; - } - if ( IP_VER((IPHdr*)enc->ip_hdr) == 4 ) - return UN4_Encode(enc, in, out); - - return UN6_Encode(enc, in, out); -} - -static ENC_STATUS UDP_Update (Packet* p, Layer* lyr, uint32_t* len) -{ - UDPHdr* h = (UDPHdr*)(lyr->start); - - *len += sizeof(*h) + p->dsize; - h->uh_len = htons((uint16_t)*len); - - - if ( !PacketWasCooked(p) || (p->packet_flags & PKT_REBUILT_FRAG) ) { - h->uh_chk = 0; - - if (IS_IP4(p)) { - pseudoheader ps; - ps.sip = ((IPHdr *)(lyr-1)->start)->ip_src.s_addr; - ps.dip = ((IPHdr *)(lyr-1)->start)->ip_dst.s_addr; - ps.zero = 0; - ps.protocol = IPPROTO_UDP; - ps.len = htons((uint16_t)*len); - h->uh_chk = in_chksum_udp(&ps, (uint16_t *)h, *len); - } else { - pseudoheader6 ps6; - memcpy(ps6.sip, &p->ip6h->ip_src.ip32, sizeof(ps6.sip)); - memcpy(ps6.dip, &p->ip6h->ip_dst.ip32, sizeof(ps6.dip)); - ps6.zero = 0; - ps6.protocol = IPPROTO_UDP; - ps6.len = htons((uint16_t)*len); - h->uh_chk = in_chksum_udp6(&ps6, (uint16_t *)h, *len); - } - } - - return ENC_OK; -} - -static void UDP_Format (EncodeFlags f, const Packet* p, Packet* c, Layer* lyr) -{ - UDPHdr* ch = (UDPHdr*)lyr->start; - c->udph = ch; - - if ( REVERSE(f) ) - { - int i = lyr - c->layers; - UDPHdr* ph = (UDPHdr*)p->layers[i].start; - - ch->uh_sport = ph->uh_dport; - ch->uh_dport = ph->uh_sport; - } - c->sp = ntohs(ch->uh_sport); - c->dp = ntohs(ch->uh_dport); -} - -//------------------------------------------------------------------------- -// TCP -// encoder creates TCP RST -// should always try to use acceptable ack since we send RSTs in a -// stateless fashion ... from rfc 793: -// -// In all states except SYN-SENT, all reset (RST) segments are validated -// by checking their SEQ-fields. A reset is valid if its sequence number -// is in the window. In the SYN-SENT state (a RST received in response -// to an initial SYN), the RST is acceptable if the ACK field -// acknowledges the SYN. -//------------------------------------------------------------------------- - -static ENC_STATUS TCP_Encode (EncState* enc, Buffer* in, Buffer* out) -{ - int len, ctl; - - TCPHdr* hi = (TCPHdr*)enc->p->layers[enc->layer-1].start; - TCPHdr* ho = (TCPHdr*)(out->base + out->end); - - UPDATE_BOUND(out, sizeof(*ho)); - - len = GET_TCP_HDR_LEN(hi) - sizeof(*hi); - UPDATE_BOUND(in, len); - ctl = (hi->th_flags & TH_SYN) ? 1 : 0; - - if ( FORWARD(enc) ) - { - ho->th_sport = hi->th_sport; - ho->th_dport = hi->th_dport; - - // th_seq depends on whether the data passes or drops - if ( DAQ_GetInterfaceMode(enc->p->pkth) != DAQ_MODE_INLINE ) - ho->th_seq = htonl(ntohl(hi->th_seq) + enc->p->dsize + ctl); - else - ho->th_seq = hi->th_seq; - - ho->th_ack = hi->th_ack; - } - else - { - ho->th_sport = hi->th_dport; - ho->th_dport = hi->th_sport; - - ho->th_seq = hi->th_ack; - ho->th_ack = htonl(ntohl(hi->th_seq) + enc->p->dsize + ctl); - } - - if ( enc->flags & ENC_FLAG_SEQ ) - { - uint32_t seq = ntohl(ho->th_seq); - seq += (enc->flags & ENC_FLAG_VAL); - ho->th_seq = htonl(seq); - } - ho->th_offx2 = 0; - SET_TCP_OFFSET(ho, (TCP_HDR_LEN >> 2)); - ho->th_win = ho->th_urp = 0; - - if ( enc->type == ENC_TCP_FIN || enc->type == ENC_TCP_PUSH ) - { - if ( enc->payLoad && enc->payLen > 0 ) - { - uint8_t* pdu = out->base + out->end; - UPDATE_BOUND(out, enc->payLen); - memcpy(pdu, enc->payLoad, enc->payLen); - } - - ho->th_flags = TH_ACK; - if ( enc->type == ENC_TCP_PUSH ) - { - ho->th_flags |= TH_PUSH; - ho->th_win = htons(65535); - } - else - { - ho->th_flags |= TH_FIN; - } - } - else - { - ho->th_flags = TH_RST | TH_ACK; - } - - // in case of ip6 extension headers, this gets next correct - enc->proto = IPPROTO_TCP; - - ho->th_sum = 0; - - if (IP_VER((IPHdr *)enc->ip_hdr) == 4) { - pseudoheader ps; - int len = BUFF_DIFF(out, ho); - - ps.sip = ((IPHdr *)(enc->ip_hdr))->ip_src.s_addr; - ps.dip = ((IPHdr *)(enc->ip_hdr))->ip_dst.s_addr; - ps.zero = 0; - ps.protocol = IPPROTO_TCP; - ps.len = htons((uint16_t)len); - ho->th_sum = in_chksum_tcp(&ps, (uint16_t *)ho, len); - } else { - pseudoheader6 ps6; - int len = BUFF_DIFF(out, ho); - - memcpy(ps6.sip, ((IP6RawHdr *)enc->ip_hdr)->ip6_src.s6_addr, sizeof(ps6.sip)); - memcpy(ps6.dip, ((IP6RawHdr *)enc->ip_hdr)->ip6_dst.s6_addr, sizeof(ps6.dip)); - ps6.zero = 0; - ps6.protocol = IPPROTO_TCP; - ps6.len = htons((uint16_t)len); - ho->th_sum = in_chksum_tcp6(&ps6, (uint16_t *)ho, len); - } - - return ENC_OK; -} - -static ENC_STATUS TCP_Update (Packet* p, Layer* lyr, uint32_t* len) -{ - TCPHdr* h = (TCPHdr*)(lyr->start); - - *len += GET_TCP_HDR_LEN(h) + p->dsize; - - if ( !PacketWasCooked(p) || (p->packet_flags & PKT_REBUILT_FRAG) ) { - h->th_sum = 0; - - if (IS_IP4(p)) { - pseudoheader ps; - ps.sip = ((IPHdr *)(lyr-1)->start)->ip_src.s_addr; - ps.dip = ((IPHdr *)(lyr-1)->start)->ip_dst.s_addr; - ps.zero = 0; - ps.protocol = IPPROTO_TCP; - ps.len = htons((uint16_t)*len); - h->th_sum = in_chksum_tcp(&ps, (uint16_t *)h, *len); - } else { - pseudoheader6 ps6; - memcpy(ps6.sip, &p->ip6h->ip_src.ip32, sizeof(ps6.sip)); - memcpy(ps6.dip, &p->ip6h->ip_dst.ip32, sizeof(ps6.dip)); - ps6.zero = 0; - ps6.protocol = IPPROTO_TCP; - ps6.len = htons((uint16_t)*len); - h->th_sum = in_chksum_tcp6(&ps6, (uint16_t *)h, *len); - } - } - - return ENC_OK; -} - -static void TCP_Format (EncodeFlags f, const Packet* p, Packet* c, Layer* lyr) -{ - TCPHdr* ch = (TCPHdr*)lyr->start; - c->tcph = ch; - - if ( REVERSE(f) ) - { - int i = lyr - c->layers; - TCPHdr* ph = (TCPHdr*)p->layers[i].start; - - ch->th_sport = ph->th_dport; - ch->th_dport = ph->th_sport; - } - c->sp = ntohs(ch->th_sport); - c->dp = ntohs(ch->th_dport); -} - -//------------------------------------------------------------------------- -// IP6 encoder -//------------------------------------------------------------------------- - -static ENC_STATUS IP6_Encode (EncState* enc, Buffer* in, Buffer* out) -{ - int len; - uint32_t start = out->end; - - IP6RawHdr* hi = (IP6RawHdr*)enc->p->layers[enc->layer-1].start; - IP6RawHdr* ho = (IP6RawHdr*)(out->base + out->end); - PROTO_ID next = NextEncoder(enc); - - UPDATE_BOUND(out, sizeof(*ho)); - - ho->ip6flow = htonl(ntohl(hi->ip6flow) & 0xFFF00000); - ho->ip6nxt = hi->ip6nxt; - - if ( FORWARD(enc) ) - { - memcpy(ho->ip6_src.s6_addr, hi->ip6_src.s6_addr, sizeof(ho->ip6_src.s6_addr)); - memcpy(ho->ip6_dst.s6_addr, hi->ip6_dst.s6_addr, sizeof(ho->ip6_dst.s6_addr)); - - ho->ip6hops = FwdTTL(enc, hi->ip6hops); - } - else - { - memcpy(ho->ip6_src.s6_addr, hi->ip6_dst.s6_addr, sizeof(ho->ip6_src.s6_addr)); - memcpy(ho->ip6_dst.s6_addr, hi->ip6_src.s6_addr, sizeof(ho->ip6_dst.s6_addr)); - - ho->ip6hops = RevTTL(enc, hi->ip6hops); - } - - enc->ip_hdr = (uint8_t*)hi; - enc->ip_len = sizeof(*hi); - - if ( next < PROTO_MAX ) - { - ENC_STATUS err = encoders[next].fencode(enc, in, out); - if ( ENC_OK != err ) return err; - } - if ( enc->proto ) - { - ho->ip6nxt = enc->proto; - enc->proto = 0; - } - len = out->end - start; - ho->ip6plen = htons((uint16_t)(len - sizeof(*ho))); - - return ENC_OK; -} - -static ENC_STATUS IP6_Update (Packet* p, Layer* lyr, uint32_t* len) -{ - IP6RawHdr* h = (IP6RawHdr*)(lyr->start); - int i = lyr - p->layers; - - // if we didn't trim payload or format this packet, - // we may not know the actual lengths because not all - // extension headers are decoded and we stop at frag6. - // in such case we do not modify the packet length. - if ( (p->packet_flags & PKT_MODIFIED) - && !(p->packet_flags & PKT_RESIZED) - ) { - *len = ntohs(h->ip6plen) + sizeof(*h); - } - else - { - if ( i + 1 == p->next_layer ) - *len += lyr->length + p->dsize; - - // w/o all extension headers, can't use just the - // fixed ip6 header length so we compute header delta - else - *len += lyr[1].start - lyr->start; - - // len includes header, remove for payload - h->ip6plen = htons((uint16_t)(*len - sizeof(*h))); - } - - return ENC_OK; -} - -static void IP6_Format (EncodeFlags f, const Packet* p, Packet* c, Layer* lyr) -{ - IP6RawHdr* ch = (IP6RawHdr*)lyr->start; - - if ( REVERSE(f) ) - { - int i = lyr - c->layers; - IP6RawHdr* ph = (IP6RawHdr*)p->layers[i].start; - - memcpy(ch->ip6_src.s6_addr, ph->ip6_dst.s6_addr, sizeof(ch->ip6_src.s6_addr)); - memcpy(ch->ip6_dst.s6_addr, ph->ip6_src.s6_addr, sizeof(ch->ip6_dst.s6_addr)); - } - if ( f & ENC_FLAG_DEF ) - { - int i = lyr - c->layers; - if ( i + 1 == p->next_layer ) - { - uint8_t* b = (uint8_t*)p->ip6_extensions[p->ip6_frag_index].data; - if ( b ) lyr->length = b - p->layers[i].start; - } - } - sfiph_build(c, ch, AF_INET6); - - // set outer to inner so this will always wind pointing to inner - c->raw_ip6h = ch; -} - -//------------------------------------------------------------------------- -// IP6 options functions -//------------------------------------------------------------------------- - -static ENC_STATUS Opt6_Encode (EncState* enc, Buffer* in, Buffer* out) -{ - // we don't encode ext headers - PROTO_ID next = NextEncoder(enc); - - if ( next < PROTO_MAX ) - { - ENC_STATUS err = encoders[next].fencode(enc, in, out); - if ( ENC_OK != err ) return err; - } - return ENC_OK; -} - -static ENC_STATUS Opt6_Update (Packet* p, Layer* lyr, uint32_t* len) -{ - int i = lyr - p->layers; - *len += lyr->length; - - if ( i + 1 == p->next_layer ) - *len += p->dsize; - - return ENC_OK; -} - -//------------------------------------------------------------------------- -// ICMP6 functions -//------------------------------------------------------------------------- - -static ENC_STATUS UN6_Encode (EncState* enc, Buffer*, Buffer* out) -{ - uint8_t* p; - uint8_t* hi = enc->p->layers[enc->layer-1].start; - IcmpHdr* ho = (IcmpHdr*)(out->base + out->end); - pseudoheader6 ps6; - int len; - -#ifdef DEBUG - if ( enc->type < ENC_UNR_NET ) - return ENC_BAD_OPT; -#endif - - enc->proto = IPPROTO_ICMPV6; - - UPDATE_BOUND(out, sizeof(*ho)); - ho->type = 1; // dest unreachable - ho->code = 4; // port unreachable - ho->cksum = 0; - ho->unused = 0; - - // ip + udp headers are copied separately because there - // may be intervening extension headers which aren't copied - - // copy original ip header - p = out->base + out->end; - UPDATE_BOUND(out, enc->ip_len); - // TBD should be able to elminate enc->ip_hdr by using layer-2 - memcpy(p, enc->ip_hdr, enc->ip_len); - ((IP6RawHdr*)p)->ip6nxt = IPPROTO_UDP; - - // copy first 8 octets of original ip data (ie udp header) - // TBD: copy up to minimum MTU worth of data - p = out->base + out->end; - UPDATE_BOUND(out, ICMP_UNREACH_DATA); - memcpy(p, hi, ICMP_UNREACH_DATA); - - len = BUFF_DIFF(out, ho); - - memcpy(ps6.sip, ((IP6RawHdr *)enc->ip_hdr)->ip6_src.s6_addr, sizeof(ps6.sip)); - memcpy(ps6.dip, ((IP6RawHdr *)enc->ip_hdr)->ip6_dst.s6_addr, sizeof(ps6.dip)); - ps6.zero = 0; - ps6.protocol = IPPROTO_ICMPV6; - ps6.len = htons((uint16_t)(len)); - - ho->cksum = in_chksum_icmp6(&ps6, (uint16_t *)ho, len); - - return ENC_OK; -} - -static ENC_STATUS ICMP6_Update (Packet* p, Layer* lyr, uint32_t* len) -{ - IcmpHdr* h = (IcmpHdr*)(lyr->start); - - *len += sizeof(*h) + p->dsize; - - if ( !PacketWasCooked(p) || (p->packet_flags & PKT_REBUILT_FRAG) ) { - pseudoheader6 ps6; - h->cksum = 0; - - memcpy(ps6.sip, &p->ip6h->ip_src.ip32, sizeof(ps6.sip)); - memcpy(ps6.dip, &p->ip6h->ip_dst.ip32, sizeof(ps6.dip)); - ps6.zero = 0; - ps6.protocol = IPPROTO_ICMPV6; - ps6.len = htons((uint16_t)*len); - h->cksum = in_chksum_icmp6(&ps6, (uint16_t *)h, *len); - } - - return ENC_OK; -} - -static void ICMP6_Format (EncodeFlags, const Packet*, Packet* c, Layer* lyr) -{ - // TBD handle nested icmp6 layers - c->icmp6h = (ICMP6Hdr*)lyr->start; -} - -//------------------------------------------------------------------------- -// GTP functions -//------------------------------------------------------------------------- - -static ENC_STATUS update_GTP_length(GTPHdr* h, int gtp_total_len ) -{ - /*The first 3 bits are version number*/ - uint8_t version = (h->flag & 0xE0) >> 5; - switch (version) - { - case 0: /*GTP v0*/ - h->length = htons((uint16_t)(gtp_total_len - GTP_V0_HEADER_LEN)); - break; - case 1: /*GTP v1*/ - h->length = htons((uint16_t)(gtp_total_len - GTP_MIN_LEN)); - break; - default: - return ENC_BAD_PROTO; - } - return ENC_OK; - -} - -static ENC_STATUS GTP_Encode (EncState* enc, Buffer* in, Buffer* out) -{ - int n = enc->p->layers[enc->layer-1].length; - int len; - - GTPHdr* hi = (GTPHdr*) (enc->p->layers[enc->layer-1].start); - GTPHdr* ho = (GTPHdr*)(out->base + out->end); - uint32_t start = out->end; - PROTO_ID next = NextEncoder(enc); - - UPDATE_BOUND(out, n); - memcpy(ho, hi, n); - - if ( next < PROTO_MAX ) - { - ENC_STATUS err = encoders[next].fencode(enc, in, out); - if (ENC_OK != err ) return err; - } - len = out->end - start; - return( update_GTP_length(ho,len)); -} - -static ENC_STATUS GTP_Update (Packet*, Layer* lyr, uint32_t* len) -{ - GTPHdr* h = (GTPHdr*)(lyr->start); - *len += lyr->length; - return( update_GTP_length(h,*len)); -} - -//------------------------------------------------------------------------- -// PPPoE functions -//------------------------------------------------------------------------- - -static ENC_STATUS PPPoE_Encode (EncState* enc, Buffer* in, Buffer* out) -{ - int n = enc->p->layers[enc->layer-1].length; - int len; - - PPPoEHdr* hi = (PPPoEHdr*)(enc->p->layers[enc->layer-1].start); - PPPoEHdr* ho = (PPPoEHdr*)(out->base + out->end); - - uint32_t start; - PROTO_ID next = NextEncoder(enc); - - UPDATE_BOUND(out, n); - memcpy(ho, hi, n); - - start = out->end; - - if ( next < PROTO_MAX ) - { - ENC_STATUS err = encoders[next].fencode(enc, in, out); - if (ENC_OK != err ) return err; - } - len = out->end - start; - ho->length = htons((uint16_t)len); - - return ENC_OK; -} - -//------------------------------------------------------------------------- -// XXX (generic) functions -//------------------------------------------------------------------------- - -static ENC_STATUS XXX_Encode (EncState* enc, Buffer* in, Buffer* out) -{ - int n = enc->p->layers[enc->layer-1].length; - - uint8_t* hi = enc->p->layers[enc->layer-1].start; - uint8_t* ho = (uint8_t*)(out->base + out->end); - PROTO_ID next = NextEncoder(enc); - - UPDATE_BOUND(out, n); - memcpy(ho, hi, n); - - if ( next < PROTO_MAX ) - { - ENC_STATUS err = encoders[next].fencode(enc, in, out); - if (ENC_OK != err ) return err; - } - return ENC_OK; -} - -// for general cases, may need to move dsize out of top, tcp, and -// udp and put in Encode_Update() (then this can be eliminated and -// xxx called instead). (another thought is to add data as a "layer"). - -#if 0 -static ENC_STATUS Top_Update (Packet* p, Layer* lyr, uint32_t* len) -{ - *len += lyr->length + p->dsize; - return ENC_OK; -} -#endif - -static ENC_STATUS XXX_Update (Packet*, Layer* lyr, uint32_t* len) -{ - *len += lyr->length; - return ENC_OK; -} - -static void XXX_Format (EncodeFlags, const Packet*, Packet*, Layer*) -{ - // nop -} - -//------------------------------------------------------------------------- -// function table: -// these must be in the same order PROTO_IDs are defined! -// all entries must have a function -//------------------------------------------------------------------------- - -EncoderFunctions encoders[PROTO_MAX] = { // FIXIT should be static - { Eth_Encode, Eth_Update, Eth_Format }, - { IP4_Encode, IP4_Update, IP4_Format }, - { UN4_Encode, ICMP4_Update, ICMP4_Format }, - { XXX_Encode, XXX_Update, XXX_Format, }, // ICMP_IP4 - { UDP_Encode, UDP_Update, UDP_Format }, - { TCP_Encode, TCP_Update, TCP_Format }, - { IP6_Encode, IP6_Update, IP6_Format }, - { Opt6_Encode, Opt6_Update, XXX_Format }, // IP6 Hop Opts - { Opt6_Encode, Opt6_Update, XXX_Format }, // IP6 Dst Opts - { UN6_Encode, ICMP6_Update, ICMP6_Format }, - { XXX_Encode, XXX_Update, XXX_Format, }, // ICMP_IP6 - { XXX_Encode, XXX_Update, VLAN_Format }, - { XXX_Encode, XXX_Update, GRE_Format }, - { XXX_Encode, XXX_Update, XXX_Format }, // ERSPAN - { PPPoE_Encode,XXX_Update, XXX_Format }, - { XXX_Encode, XXX_Update, XXX_Format }, // PPP Encap - { XXX_Encode, XXX_Update, XXX_Format }, // MPLS - { XXX_Encode, XXX_Update, XXX_Format, }, // ARP - { GTP_Encode, GTP_Update, XXX_Format, }, // GTP - { XXX_Encode, XXX_Update, XXX_Format, } // Auth Header -}; - diff --git a/src/protocols/encode.h b/src/protocols/encode.h deleted file mode 100644 index 60d74172d..000000000 --- a/src/protocols/encode.h +++ /dev/null @@ -1,124 +0,0 @@ -/**************************************************************************** - * -** Copyright (C) 2014 Cisco and/or its affiliates. All rights reserved. - * Copyright (C) 2005-2013 Sourcefire, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License Version 2 as - * published by the Free Software Foundation. You may not use, modify or - * distribute this program under any other version of the GNU General - * Public License. - * - * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - ****************************************************************************/ - -// @file encode.h -// @author Russ Combs - -#ifndef ENCODE_H -#define ENCODE_H - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include "decode.h" - -extern Packet *encode_pkt; -extern uint64_t total_rebuilt_pkts; - -void Encode_Init(void); -void Encode_Term(void); - -typedef enum { - ENC_TCP_FIN, ENC_TCP_RST, - ENC_UNR_NET, ENC_UNR_HOST, - ENC_UNR_PORT, ENC_UNR_FW, - ENC_TCP_PUSH, - ENC_MAX -} EncodeType; - -#define ENC_FLAG_FWD 0x80000000 // send in forward direction -#define ENC_FLAG_SEQ 0x40000000 // VAL bits contain seq adj -#define ENC_FLAG_ID 0x20000000 // use randomized IP ID -#define ENC_FLAG_NET 0x10000000 // stop after innermost network (ip4/6) layer -#define ENC_FLAG_DEF 0x08000000 // stop before innermost ip4 opts or ip6 frag header -#define ENC_FLAG_RAW 0x04000000 // don't encode outer eth header (this is raw ip) -#define ENC_FLAG_RES 0x03000000 // bits reserved for future use -#define ENC_FLAG_VAL 0x00FFFFFF // bits for adjusting seq and/or ack - -typedef uint32_t EncodeFlags; - -// orig must be the current packet from the interface to -// ensure proper encoding (not the reassembled packet). -// len is number of bytes in the encoded packet upon return -// (or 0 if the returned pointer is null). -const uint8_t* Encode_Reject( - EncodeType, EncodeFlags, const Packet* orig, uint32_t* len); - -const uint8_t* Encode_Response( - EncodeType, EncodeFlags, const Packet* orig, uint32_t* len, - const uint8_t* payLoad, uint32_t payLen); - -// allocate a Packet for later formatting (cloning) -Packet* Encode_New(void); - -// release the allocated Packet -void Encode_Delete(Packet*); - -// orig is the wire pkt; clone was obtained with New() -int Encode_Format( - EncodeFlags, const Packet* orig, Packet* clone, PseudoPacketType); - -#ifdef HAVE_DAQ_ADDRESS_SPACE_ID -int Encode_Format_With_DAQ_Info ( - EncodeFlags f, const Packet* p, Packet* c, PseudoPacketType type, - const DAQ_PktHdr_t*, uint32_t opaque); - -#elif defined(HAVE_DAQ_ACQUIRE_WITH_META) -int Encode_Format_With_DAQ_Info ( - EncodeFlags f, const Packet* p, Packet* c, PseudoPacketType type, - uint32_t opaque); -#endif - -// update length and checksum fields in layers and caplen, etc. -void Encode_Update(Packet*); - -// Set the destination MAC address -void Encode_SetDstMAC(uint8_t* ); - -static inline void Encode_SetPkt(Packet* p) -{ - encode_pkt = p; -} - -static inline Packet* Encode_GetPkt(void) -{ - return encode_pkt; -} - -static inline void Encode_Reset(void) -{ - Encode_SetPkt(NULL); -} - -static inline void UpdateRebuiltPktCount(void) -{ - total_rebuilt_pkts++; -} - -static inline uint64_t GetRebuiltPktCount(void) -{ - return total_rebuilt_pkts; -} - -#endif - diff --git a/src/protocols/sf_protocols.h b/src/protocols/sf_protocols.h deleted file mode 100644 index a190ccb58..000000000 --- a/src/protocols/sf_protocols.h +++ /dev/null @@ -1,109 +0,0 @@ -/**************************************************************************** - * -** Copyright (C) 2014 Cisco and/or its affiliates. All rights reserved. - * Copyright (C) 2005-2013 Sourcefire, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License Version 2 as - * published by the Free Software Foundation. You may not use, modify or - * distribute this program under any other version of the GNU General - * Public License. - * - * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - ****************************************************************************/ - -#ifndef SF_PROTOCOLS_H -#define SF_PROTOCOLS_H - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -typedef enum { - PROTO_ETH, // DecodeEthPkt - - PROTO_IP4, // DecodeIP - // DecodeIPOptions - handled with IP4 - PROTO_ICMP4, // DecodeICMP - PROTO_ICMP_IP4, // DecodeICMPEmbeddedIP - - PROTO_UDP, // DecodeUDP - PROTO_TCP, // DecodeTCP - // DecodeTCPOptions - handled with TCP - - PROTO_IP6, // DecodeIPV6 - // DecodeIPV6Extensions - nothing to do here, calls below - PROTO_IP6_HOP_OPTS, // DecodeIPV6Options - ip6 hop, dst, rte, and frag exts - PROTO_IP6_DST_OPTS, - PROTO_ICMP6, // DecodeICMP6 - PROTO_ICMP_IP6, // DecodeICMPEmbeddedIP6 - PROTO_VLAN, // DecodeVlan - PROTO_GRE, // DecodeGRE - // DecodeTransBridging - basically same as DecodeEthPkt - PROTO_ERSPAN, // DecodeERSPANType2 and DecodeERSPANType3 - PROTO_PPPOE, // DecodePPPoEPkt - PROTO_PPP_ENCAP, // DecodePppPktEncapsulated - PROTO_MPLS, // DecodeMPLS - decoder changes pkth len/caplen! - // DecodeEthOverMPLS - basically same as straight eth - PROTO_ARP, // DecodeARP - PROTO_GTP, // DecodeGTP - PROTO_AH, // DecodeAH - Authentication Header (IPSec stuff) - -#ifndef NO_NON_ETHER_DECODER - PROTO_TR, // DecodeTRPkt - PROTO_FDDI, // DecodeFDDIPkt - PROTO_LSLL, // DecodeLinuxSLLPkt sockaddr_ll for "any" device and - // certain misbehaving link layer encapsulations - PROTO_80211, // DecodeIEEE80211Pkt - PROTO_SLIP, // DecodeSlipPkt - actually, based on header size, this - // must be CSLIP (TCP/IP header compression) but all it - // does is skip over the presumed header w/o expanding - // and then jumps into IP4 decoding only; also, the actual - // esc/end sequences must already have been removed because - // there is no attempt to do that. - PROTO_L2I4, // DecodeI4LRawIPPkt - always skips 2 bytes and then does - // IP4 decoding only - PROTO_L2I4C, // DecodeI4LCiscoIPPkt -always skips 4 bytes and then does - // IP4 decoding only - PROTO_CHDLC, // DecodeChdlcPkt - skips 4 bytes and decodes IP4 only. - PROTO_PFLOG, // DecodePflog - PROTO_OLD_PFLOG, // DecodeOldPflog - PROTO_PPP, // DecodePppPkt - weird - optionally skips addr and cntl - // bytes; what about flag and protocol? - // calls only DecodePppPktEncapsulated. - PROTO_PPP_SERIAL, // DecodePppSerialPkt - also weird - requires addr, cntl, - // and proto (no flag) but optionally skips only 2 bytes - // (presumably the trailer w/chksum is already stripped) - // Calls either DecodePppPktEncapsulated or DecodeChdlcPkt. - PROTO_ENC, // DecodeEncPkt - skips 12 bytes and decodes IP4 only. - // (add family + "spi" + "flags" - don't know what this is) - PROTO_EAP, // DecodeEAP - PROTO_EAPOL, // DecodeEapol - leaf decoder - PROTO_EAPOL_KEY, // DecodeEapolKey - leaf decoder -#endif // NO_NON_ETHER_DECODER - - PROTO_MAX -} PROTO_ID; - - // DecodeIPX - just counts; no decoding - // DecodeEthLoopback - same as ipx - // DecodeRawPkt - jumps straight into IP4 decoding - // there is nothing to do - // DecodeNullPkt - same as DecodeRawPkt - -typedef struct { - PROTO_ID proto; - uint16_t length; - uint8_t* start; -} Layer; - -#endif // __PROTOCOLS_H__ -