[prev in list] [next in list] [prev in thread] [next in thread]
List: snort-devel
Subject: Re: [Snort-devel] [PATCH] Add non-IP layer 3 detection via new
From: Joshua Kinard <kumba () gentoo ! org>
Date: 2011-12-27 0:06:35
Message-ID: 4EF90C0B.2000104 () gentoo ! org
[Download RAW message or body]
With the release of snort-2.9.2 final, I rebased my work for the ether_type
rule option. Some of the data types changed which required it.
In addition, I added the bit of code to DecodeIEEE80211Pkt to make it work
with ether_type (no time to fix the mess w/ LLC/SNAP frame decoding right
now), and I added documentation to the snort manual for the new option and
tested it once I got the TeX tools setup and working.
Attached patch only modifies the snort_manual.tex file, so the PDF would
need to be regenerated in an upcoming release if this is accepted.
And lets not forget the hyperlinks in the manual next time :)
Changes:
doc/snort_manual.tex | 105 ++++++
src/decode.c | 120 +++++++
src/decode.h | 27 +
src/detect.c | 42 +-
src/detection-plugins/Makefile.am | 3
src/detection-plugins/Makefile.in | 8
src/detection-plugins/detection_options.c | 14
src/detection-plugins/sp_ether_type.c | 361 ++++++++++++++++++++++++
src/detection-plugins/sp_ether_type.h | 125 ++++++++
src/dynamic-plugins/sf_engine/sf_snort_packet.h | 3
src/fpcreate.c | 252 +++++++++++++---
src/fpcreate.h | 7
src/fpdetect.c | 241 ++++++++++------
src/fpdetect.h | 12
src/parser.c | 183 ++++++++----
src/plugbase.c | 2
src/plugin_enum.h | 1
src/rule_option_types.h | 3
src/sfutil/sfportobject.h | 7
src/snort.c | 14
src/snort.h | 4
21 files changed, 1313 insertions(+), 221 deletions(-)
Cheers!
--
Joshua Kinard
Gentoo/MIPS
kumba@gentoo.org
4096R/D25D95E3 2011-03-28
"The past tempts us, the present confuses us, the future frightens us. And
our lives slip away, moment by moment, lost in that vast, terrible in-between."
--Emperor Turhan, Centauri Republic
["snort-2.9.2-ether_type-support.patch" (text/plain)]
diff --git a/doc/snort_manual.tex b/doc/snort_manual.tex
index 23111c0..020415d 100644
--- a/doc/snort_manual.tex
+++ b/doc/snort_manual.tex
@@ -13402,9 +13402,9 @@ database:
\subsection{Protocols}
-The next field in a rule is the protocol. There are four protocols that Snort
-currently analyzes for suspicious behavior -- TCP, UDP, ICMP, and IP. In the
-future there may be more, such as ARP, IGRP, GRE, OSPF, RIP, IPX, etc.
+The next field in a rule is the protocol. There are five protocols that Snort
+currently analyzes for suspicious behavior -- TCP, UDP, ICMP, IP, and ETH. In
+the future there may be more, such as SCTP, DCCP, IGRP, GRE, OSPF, RIP, etc.
\subsection{IP Addresses}
@@ -16694,6 +16694,104 @@ This example looks for IGMP traffic.
alert ip any any -> any any (ip_proto:igmp;)
\end{verbatim}
+\subsection{ether\_type}
+
+The ether\_type keyword allows checks against the Ethernet II type.
+
+\subsubsection{Format}
+
+\begin{verbatim}
+ ether_type:[!|>|<] <hex code> | <name>
+\end{verbatim}
+
+Where \texttt{<hex code>} is a value ranging from \texttt{0x0600} to \texttt{0xffff}
+OR where \texttt{<name>} is a value from table \ref{ethertypes}.
+
+\begin{table}[h]
+\begin{center}
+\caption{Named Ethertypes}
+\label{ethertypes}
+
+\begin{tabular}{| l | l | p{2.8in} |}
+\hline
+{\bf Name} & {\bf Value} & {\bf Description}\\
+\hline
+
+\texttt{xerox} & \texttt{0x0600} & Xerox NS IDP\\
+\hline
+\texttt{ipv4} & \texttt{0x0800} & IP version 4\\
+\hline
+\texttt{x75} & \texttt{0x0801} & X.75 Internet\\
+\hline
+\texttt{nbs} & \texttt{0x0802} & NBS Internet\\
+\hline
+\texttt{ecma} & \texttt{0x0803} & ECMA Internet\\
+\hline
+\texttt{chaos} & \texttt{0x0804} & CHAOSNet\\
+\hline
+\texttt{x25} & \texttt{0x0805} & X.25 Level 3\\
+\hline
+\texttt{arp} & \texttt{0x0806} & Address Resolution Protocol\\
+\hline
+\texttt{rarp} & \texttt{0x0835} & Reverse ARP\\
+\hline
+\texttt{wol} & \texttt{0x0842} & Wake On LAN\\
+\hline
+\texttt{ax25} & \texttt{0x08ff} & AX.25 over Ethernet (G8BPQ)\\
+\hline
+\texttt{decnet} & \texttt{0x6003} & DECnet DNA\\
+\hline
+\texttt{apple} & \texttt{0x809b} & Appletalk\\
+\hline
+\texttt{aarp} & \texttt{0x80f3} & Appletalk ARP\\
+\hline
+\texttt{vlan} & \texttt{0x8100} & VLAN Tagged 802.1q\\
+\hline
+\texttt{netbeui} & \texttt{0x8191} & NetBEUI\\
+\hline
+\texttt{ipx} & \texttt{0x8137} & Novell IPX/SPX\\
+\hline
+\texttt{snmp} & \texttt{0x814c} & SNMP over Ethernet\\
+\hline
+\texttt{ipv6} & \texttt{0x86dd} & IP version 6\\
+\hline
+\texttt{slow} & \texttt{0x8809} & Slow Protocols\\
+\hline
+\texttt{ppp} & \texttt{0x880b} & Point-to-Point Protocol\\
+\hline
+\texttt{mpls} & \texttt{0x8847} & MPLS Unicast\\
+\hline
+\texttt{pppoed} & \texttt{0x8863} & PPP over Ethernet Discovery\\
+\hline
+\texttt{pppoes} & \texttt{0x8864} & PPP over Ethernet Session\\
+\hline
+\texttt{eapol} & \texttt{0x888e} & EAPOL (EAP over LAN), IEEE 802.1x\\
+\hline
+\texttt{aoe} & \texttt{0x88a2} & ATA over Ethernet\\
+\hline
+\texttt{lldp} & \texttt{0x88cc} & Logical Link Discovery Protocol\\
+\hline
+\texttt{fcoe} & \texttt{0x8906} & FibreChannel over Ethernet\\
+\hline
+\texttt{fip} & \texttt{0x8914} & FCoE Initialization Protocol\\
+\hline
+\texttt{tte} & \texttt{0x891d} & TTEthernet\\
+\hline
+\texttt{loop} & \texttt{0x9000} & Loopback\\
+\hline
+
+\end{tabular}
+\end{center}
+\end{table}
+
+\subsubsection{Example}
+
+This example looks for a NetWare server named FOOBAR in IPX traffic.
+
+\begin{verbatim}
+ alert eth any any -> any any (ether_type:ipx; content:"FOOBAR";)
+\end{verbatim}
+
\subsection{sameip}
The sameip keyword allows rules to check if the source ip is the same as the
@@ -17516,6 +17614,7 @@ beginning of any rule:
\begin{itemize}
\item \texttt{dsize}
+\item \texttt{ether\_type}
\item \texttt{flags}
\item \texttt{flow}
\item \texttt{fragbits}
diff --git a/src/decode.c b/src/decode.c
index 26d4cf4..0d5b349 100644
--- a/src/decode.c
+++ b/src/decode.c
@@ -777,8 +777,21 @@ void DecodeEthPkt(Packet * p, const DAQ_PktHdr_t * pkthdr, const \
uint8_t * pkt) ntohs(p->eh->ether_type), p->pkth->pktlen)
);
+ /* Set some convienience pointers for eth rules. */
+ p->eth_data = (pkt + sizeof(*p->eh));
+ p->eth_dsize = (uint16_t)(cap_len - ETHERNET_HEADER_LEN);
+ p->eth_type = ntohs(p->eh->ether_type);
+ p->dsize = p->eth_dsize;
+
+ if (ScIdsMode())
+ {
+ /* See if there are any ether_type only rules that match */
+ fpEvalEtherTypeOnlyRules(snort_conf->eth_type_only_lists, p);
+ p->proto_bits |= PROTO_BIT__ETH_II;
+ }
+
/* grab out the network type */
- switch(ntohs(p->eh->ether_type))
+ switch(p->eth_type)
{
case ETHERNET_TYPE_IP:
DEBUG_WRAP(
@@ -891,7 +904,20 @@ void DecodeTransBridging(const uint8_t *pkt, const uint32_t len, \
Packet *p) p->eh = (EtherHdr *)pkt;
PushLayer(PROTO_ETH, p, pkt, sizeof(*p->eh));
- switch (ntohs(p->eh->ether_type))
+ /* Set some convienience pointers for eth rules. */
+ p->eth_data = (pkt + sizeof(*p->eh));
+ p->eth_dsize = (uint16_t)(len - ETHERNET_HEADER_LEN);
+ p->eth_type = ntohs(p->eh->ether_type);
+ p->dsize = p->eth_dsize;
+
+ if (ScIdsMode())
+ {
+ /* See if there are any ether_type only rules that match */
+ fpEvalEtherTypeOnlyRules(snort_conf->eth_type_only_lists, p);
+ p->proto_bits |= PROTO_BIT__ETH_II;
+ }
+
+ switch (p->eth_type)
{
case ETHERNET_TYPE_IP:
DecodeIP(pkt + ETHERNET_HEADER_LEN, len - ETHERNET_HEADER_LEN, p);
@@ -1078,10 +1104,13 @@ void DecodeMPLS(const uint8_t* pkt, const uint32_t len, \
Packet* p) exp = (uint8_t)(mpls_h & 0x0000000E);
label = (mpls_h>>4) & 0x000FFFFF;
- if((label<NUM_RESERVED_LABELS)&&((iRet = checkMplsHdr(label, exp, bos, ttl, \
p)) < 0)) + if ((label < NUM_RESERVED_LABELS) &&
+ ((iRet = checkMplsHdr(label, exp, bos, ttl, p)) < 0))
+ {
return;
+ }
- if( bos )
+ if (bos)
{
p->mplsHdr.label = label;
p->mplsHdr.exp = exp;
@@ -1155,7 +1184,8 @@ void DecodeEthOverMPLS(const uint8_t* pkt, const uint32_t len, \
Packet* p) }
/* lay the ethernet structure over the packet data */
- p->eh = (EtherHdr *) pkt; // FIXTHIS squashes outer eth!
+ /* FIXME: Broken if PWMCW (RFC 4385) is in use. Will be off by 4 bytes. */
+ p->eh = (EtherHdr *) pkt; /* FIXME: squashes outer eth! */
PushLayer(PROTO_ETH, p, pkt, sizeof(*p->eh));
DEBUG_WRAP(
@@ -1163,8 +1193,22 @@ void DecodeEthOverMPLS(const uint8_t* pkt, const uint32_t len, \
Packet* p)
*p->eh->ether_src, *p->eh->ether_dst);
);
+ /* Set some convienience pointers for eth rules. */
+ /* FIXME: eth_data is broken if PWMCW (RFC 4385) is in use. Will be off by 4 \
bytes. */ + p->eth_data = (p->pkt + ETHERNET_HEADER_LEN); /* FIXME: squashes \
the orig eth data. */ + p->eth_dsize = (uint16_t)(len - ETHERNET_HEADER_LEN);
+ p->eth_type = ntohs(p->eh->ether_type);
+ p->dsize = p->eth_dsize;
+
+ if (ScIdsMode())
+ {
+ /* See if there are any ether_type only rules that match */
+ fpEvalEtherTypeOnlyRules(snort_conf->eth_type_only_lists, p);
+ p->proto_bits |= PROTO_BIT__ETH_II;
+ }
+
/* grab out the network type */
- switch(ntohs(p->eh->ether_type))
+ switch(p->eth_type)
{
case ETHERNET_TYPE_IP:
DEBUG_WRAP(
@@ -1282,7 +1326,7 @@ void DecodeVlan(const uint8_t * pkt, const uint32_t len, Packet \
* p) );
/* check to see if we've got an encapsulated LLC layer
- * http://www.geocities.com/billalexander/ethernet.html
+ * http://web.archive.org/web/20091027113048/http://geocities.com/BillAlexander/ethernet.html
*/
if(ntohs(p->vh->vth_proto) <= ETHERNET_MAX_LEN_ENCAP)
{
@@ -1338,7 +1382,20 @@ void DecodeVlan(const uint8_t * pkt, const uint32_t len, \
Packet * p)
PushLayer(PROTO_VLAN, p, pkt, sizeof(*p->vh));
- switch(ntohs(p->ehllcother->proto_id))
+ /* Set some convienience pointers for eth rules. */
+ p->eth_data = (p->pkt + LEN_VLAN_LLC_OTHER);
+ p->eth_dsize = (uint16_t)(len - LEN_VLAN_LLC_OTHER);
+ p->eth_type = ntohs(p->ehllcother->proto_id);
+ p->dsize = p->eth_dsize;
+
+ if (ScIdsMode())
+ {
+ /* See if there are any ether_type only rules that match */
+ fpEvalEtherTypeOnlyRules(snort_conf->eth_type_only_lists, p);
+ p->proto_bits |= PROTO_BIT__ETH_II;
+ }
+
+ switch(p->eth_type)
{
case ETHERNET_TYPE_IP:
DecodeIP(p->pkt + LEN_VLAN_LLC_OTHER,
@@ -1403,7 +1460,20 @@ void DecodeVlan(const uint8_t * pkt, const uint32_t len, \
Packet * p) {
PushLayer(PROTO_VLAN, p, pkt, sizeof(*p->vh));
- switch(ntohs(p->vh->vth_proto))
+ /* Set some convienience pointers for eth rules. */
+ p->eth_data = (pkt + sizeof(VlanTagHdr));
+ p->eth_dsize = (uint16_t)(len - sizeof(VlanTagHdr));
+ p->eth_type = ntohs(p->vh->vth_proto);
+ p->dsize = p->eth_dsize;
+
+ if (ScIdsMode())
+ {
+ /* See if there are any ether_type only rules that match */
+ fpEvalEtherTypeOnlyRules(snort_conf->eth_type_only_lists, p);
+ p->proto_bits |= PROTO_BIT__ETH_II;
+ }
+
+ switch(p->eth_type)
{
case ETHERNET_TYPE_IP:
DecodeIP(pkt + sizeof(VlanTagHdr),
@@ -4900,12 +4970,25 @@ void DecodeGRE(const uint8_t *pkt, const uint32_t len, Packet \
*p) PushLayer(PROTO_GRE, p, pkt, hlen);
payload_len = len - hlen;
+ /* Set some convienience pointers for eth rules. */
+ p->eth_data = (pkt + hlen); /* FIXME: squashes the orig eth data. */
+ p->eth_dsize = (uint16_t)payload_len;
+ p->eth_type = ntohs(p->greh->ether_type);
+ p->dsize = p->eth_dsize;
+
+ if (ScIdsMode())
+ {
+ /* See if there are any ether_type only rules that match */
+ fpEvalEtherTypeOnlyRules(snort_conf->eth_type_only_lists, p);
+ p->proto_bits |= PROTO_BIT__ETH_II;
+ }
+
/* 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))
+ switch (p->eth_type)
{
case ETHERNET_TYPE_IP:
DecodeIP(pkt + hlen, payload_len, p);
@@ -6218,7 +6301,22 @@ void DecodeIEEE80211Pkt(Packet * p, const DAQ_PktHdr_t * \
pkthdr,
printf(" PROTO: 0x%04X\n", ntohs(p->ehllcother->proto_id));
#endif
- switch(ntohs(p->ehllcother->proto_id))
+ /* Set some convienience pointers for eth rules. */
+ p->eth_data = (p->pkt + IEEE802_11_DATA_HDR_LEN + sizeof(EthLlc) +
+ sizeof(EthLlcOther));
+ p->eth_dsize = (uint16_t)(cap_len - IEEE802_11_DATA_HDR_LEN - \
sizeof(EthLlc) - + sizeof(EthLlcOther));
+ p->eth_type = ntohs(p->ehllcother->proto_id);
+ p->dsize = p->eth_dsize;
+
+ if (ScIdsMode())
+ {
+ /* See if there are any ether_type only rules that match */
+ fpEvalEtherTypeOnlyRules(snort_conf->eth_type_only_lists, p);
+ p->proto_bits |= PROTO_BIT__ETH_II;
+ }
+
+ switch(p->eth_type)
{
case ETHERNET_TYPE_IP:
DecodeIP(p->pkt + IEEE802_11_DATA_HDR_LEN + sizeof(EthLlc) +
diff --git a/src/decode.h b/src/decode.h
index 1941181..6c39e63 100644
--- a/src/decode.h
+++ b/src/decode.h
@@ -70,6 +70,15 @@
#define ETHERNET_TYPE_MPLS_UNICAST 0x8847
#define ETHERNET_TYPE_MPLS_MULTICAST 0x8848
+/*
+ * Raw Ethernet II frames don't have a direct identifier. For use within
+ * Snort, the value 0x2ffff (chosen at random) should be out of the range
+ * of any other supported protocols and will serve to identify a raw
+ * ethernet II rule from other rules.
+ */
+#define ETH_II_FRAME 0x2ffff
+
+
#define ETH_DSAP_SNA 0x08 /* SNA */
#define ETH_SSAP_SNA 0x00 /* SNA */
#define ETH_DSAP_STP 0x42 /* Spanning Tree Protocol */
@@ -632,6 +641,9 @@ struct enc_header {
#define PKT_STREAM_ORDER_BAD 0x02000000 /* this stream had at last one gap */
#define PKT_REASSEMBLED_OLD 0x04000000 /* for backwards compat with so rules */
+/* Packet is an ETH_II frame rule */
+#define PKT_ETH_II_RULE 0x08000000
+
// 0x0F800000 are available
#define PKT_PDU_FULL (PKT_PDU_HEAD | PKT_PDU_TAIL)
@@ -872,7 +884,7 @@ typedef struct _Pflog3_hdr
#define PFLOG3_HDRMIN (PFLOG3_HDRLEN - PFLOG_PADLEN)
/*
- * ssl_pkttype values.
+ * sll_pkttype values.
*/
#define LINUX_SLL_HOST 0
@@ -881,7 +893,7 @@ typedef struct _Pflog3_hdr
#define LINUX_SLL_OTHERHOST 3
#define LINUX_SLL_OUTGOING 4
-/* ssl protocol values */
+/* sll protocol values */
#define LINUX_SLL_P_802_3 0x0001 /* Novell 802.3 frames without 802.2 LLC \
header */ #define LINUX_SLL_P_802_2 0x0004 /* 802.2 frames (not D/I/X \
Ethernet) */ @@ -980,6 +992,7 @@ typedef struct _WifiHdr
#define SET_IP_HLEN(iph, value) ((iph)->ip_verhl = (unsigned char)(((iph)->ip_verhl \
& 0xf0) | (value & 0x0f)))
#define NUM_IP_PROTOS 256
+#define NUM_ETH_TYPES 65535
/* Last updated 6/2/2010.
Source: http://www.iana.org/assignments/protocol-numbers/protocol-numbers.xml */
@@ -1656,6 +1669,7 @@ typedef struct _Packet
const uint8_t *ip_frag_start;
const uint8_t *ip_options_data;
const uint8_t *tcp_options_data;
+ const uint8_t *eth_data; /* ETH_II Frame payload pointer */
//^^^-----------------------------
void *ssnptr; /* for tcp session tracking info... */
@@ -1704,6 +1718,8 @@ typedef struct _Packet
uint16_t alt_dsize; /* the dsize of a packet before munging (used for \
log)*/
uint16_t actual_ip_len; /* for logging truncated pkts (usually by small \
snaplen)*/ uint16_t outer_ip_dsize; /* Outer IP payload size */
+ uint16_t eth_dsize; /* ETH_II frame payload size */
+ uint16_t eth_type; /* ETH_II Type. decode.c stores here so other \
things can find it. */ //^^^-----------------------------
uint16_t frag_offset; /* fragment offset number */
@@ -1801,6 +1817,7 @@ typedef struct _Packet
#define PROTO_BIT__ICMP 0x0010
#define PROTO_BIT__TEREDO 0x0020
#define PROTO_BIT__GTP 0x0040
+#define PROTO_BIT__ETH_II 0x0080
#define PROTO_BIT__ALL 0xffff
#define IsIP(p) (IPH_IS_VALID(p))
@@ -1819,8 +1836,10 @@ typedef struct _Packet
#define BIT(i) (0x1 << (i-1))
#ifdef SUP_IP6
-/* Sets the callbacks to point at the family selected by
- * * "family". "family" is either AF_INET or AF_INET6 */
+/*
+ * Sets the callbacks to point at the family selected by
+ * "family". "family" is either AF_INET or AF_INET6
+ */
#define CALLBACK_IP 0
#define CALLBACK_ICMP_ORIG 1
diff --git a/src/detect.c b/src/detect.c
index c4d9185..d83d38c 100644
--- a/src/detect.c
+++ b/src/detect.c
@@ -494,38 +494,38 @@ int Detect(Packet * p)
int detected = 0;
PROFILE_VARS;
- if ((p == NULL) || !IPH_IS_VALID(p))
- {
+ if (!p)
return 0;
- }
-
- if (!snort_conf->ip_proto_array[GET_IPH_PROTO(p)])
+ if (IPH_IS_VALID(p))
{
+ if (!snort_conf->ip_proto_array[GET_IPH_PROTO(p)])
+ {
#ifdef GRE
# ifdef SUP_IP6
- switch (p->outer_family)
- {
- case AF_INET:
- if (!snort_conf->ip_proto_array[p->outer_ip4h.ip_proto])
- return 0;
- break;
+ switch (p->outer_family)
+ {
+ case AF_INET:
+ if (!snort_conf->ip_proto_array[p->outer_ip4h.ip_proto])
+ return 0;
+ break;
- case AF_INET6:
- if (!snort_conf->ip_proto_array[p->outer_ip6h.next])
- return 0;
- break;
+ case AF_INET6:
+ if (!snort_conf->ip_proto_array[p->outer_ip6h.next])
+ return 0;
+ break;
- default:
- return 0;
- }
+ default:
+ return 0;
+ }
# else
- if ((p->outer_iph == NULL) || \
!snort_conf->ip_proto_array[p->outer_iph->ip_proto])
- return 0;
+ if ((p->outer_iph == NULL) || \
!snort_conf->ip_proto_array[p->outer_iph->ip_proto]) + return 0;
# endif /* SUP_IP6 */
#else
- return 0;
+ return 0;
#endif /* GRE */
+ }
}
if (p->packet_flags & PKT_PASS_RULE)
diff --git a/src/detection-plugins/Makefile.am b/src/detection-plugins/Makefile.am
index af40c8e..0618383 100644
--- a/src/detection-plugins/Makefile.am
+++ b/src/detection-plugins/Makefile.am
@@ -61,7 +61,8 @@ sp_urilen_check.c sp_urilen_check.h \
sp_file_data.c sp_file_data.h \
sp_base64_decode.c sp_base64_decode.h \
sp_base64_data.c sp_base64_data.h \
-sp_pkt_data.c sp_pkt_data.h
+sp_pkt_data.c sp_pkt_data.h \
+sp_ether_type.c sp_ether_type.h
copy_files = \
if test -f $$dst_file; then \
diff --git a/src/detection-plugins/Makefile.in b/src/detection-plugins/Makefile.in
index 593397c..2a7f2ee 100644
--- a/src/detection-plugins/Makefile.in
+++ b/src/detection-plugins/Makefile.in
@@ -72,7 +72,8 @@ am__libspd_a_SOURCES_DIST = detection_options.c detection_options.h \
\ sp_tcp_win_check.h sp_ttl_check.c sp_ttl_check.h \
sp_urilen_check.c sp_urilen_check.h sp_file_data.c \
sp_file_data.h sp_base64_decode.c sp_base64_decode.h \
- sp_base64_data.c sp_base64_data.h sp_pkt_data.c sp_pkt_data.h
+ sp_base64_data.c sp_base64_data.h sp_pkt_data.c sp_pkt_data.h \
+ sp_ether_type.c sp_ether_type.h
@BUILD_REACT_TRUE@am__objects_1 = sp_react.$(OBJEXT)
@BUILD_RESPOND3_TRUE@am__objects_2 = sp_respond3.$(OBJEXT)
am_libspd_a_OBJECTS = detection_options.$(OBJEXT) sp_asn1.$(OBJEXT) \
@@ -94,7 +95,7 @@ am_libspd_a_OBJECTS = detection_options.$(OBJEXT) sp_asn1.$(OBJEXT) \
\ sp_tcp_win_check.$(OBJEXT) sp_ttl_check.$(OBJEXT) \
sp_urilen_check.$(OBJEXT) sp_file_data.$(OBJEXT) \
sp_base64_decode.$(OBJEXT) sp_base64_data.$(OBJEXT) \
- sp_pkt_data.$(OBJEXT)
+ sp_pkt_data.$(OBJEXT) sp_ether_type.$(OBJEXT)
nodist_libspd_a_OBJECTS = sf_snort_plugin_hdropts.$(OBJEXT)
libspd_a_OBJECTS = $(am_libspd_a_OBJECTS) $(nodist_libspd_a_OBJECTS)
DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
@@ -301,7 +302,8 @@ sp_urilen_check.c sp_urilen_check.h \
sp_file_data.c sp_file_data.h \
sp_base64_decode.c sp_base64_decode.h \
sp_base64_data.c sp_base64_data.h \
-sp_pkt_data.c sp_pkt_data.h
+sp_pkt_data.c sp_pkt_data.h \
+sp_ether_type.c sp_ether_type.h
copy_files = \
if test -f $$dst_file; then \
diff --git a/src/detection-plugins/detection_options.c \
b/src/detection-plugins/detection_options.c index 8bf95ea..aedfaea 100644
--- a/src/detection-plugins/detection_options.c
+++ b/src/detection-plugins/detection_options.c
@@ -69,6 +69,7 @@
#include "sp_isdataat.h"
#include "sp_pattern_match.h"
#include "sp_pcre.h"
+#include "sp_ether_type.h"
#ifdef ENABLE_REACT
#include "sp_react.h"
#endif
@@ -225,6 +226,9 @@ uint32_t detection_option_hash_func(SFHASHFCN *p, unsigned char \
*k, int n) case RULE_OPTION_TYPE_URILEN:
hash = UriLenCheckHash(key->option_data);
break;
+ case RULE_OPTION_TYPE_ETHER_TYPE:
+ hash = EtherTypeHash(key->option_data);
+ break;
#ifdef DYNAMIC_PLUGIN
case RULE_OPTION_TYPE_HDR_OPT_CHECK:
hash = HdrOptCheckHash(key->option_data);
@@ -379,6 +383,9 @@ int detection_option_key_compare_func(const void *k1, const void \
*k2, size_t n) case RULE_OPTION_TYPE_URILEN:
ret = UriLenCheckCompare(key1->option_data, key2->option_data);
break;
+ case RULE_OPTION_TYPE_ETHER_TYPE:
+ ret = EtherTypeCompare(key1->option_data, key2->option_data);
+ break;
#ifdef DYNAMIC_PLUGIN
case RULE_OPTION_TYPE_HDR_OPT_CHECK:
ret = HdrOptCheckCompare(key1->option_data, key2->option_data);
@@ -516,6 +523,9 @@ int detection_hash_free_func(void *option_key, void *data)
case RULE_OPTION_TYPE_URILEN:
free(key->option_data);
break;
+ case RULE_OPTION_TYPE_ETHER_TYPE:
+ free(key->option_data);
+ break;
#ifdef DYNAMIC_PLUGIN
case RULE_OPTION_TYPE_HDR_OPT_CHECK:
break;
@@ -771,7 +781,8 @@ char *option_type_str[] =
"RULE_OPTION_TYPE_TCP_SEQ",
"RULE_OPTION_TYPE_TCP_WIN",
"RULE_OPTION_TYPE_TTL",
- "RULE_OPTION_TYPE_URILEN"
+ "RULE_OPTION_TYPE_URILEN",
+ "RULE_OPTION_TYPE_ETHER_TYPE"
#ifdef DYNAMIC_PLUGIN
,
"RULE_OPTION_TYPE_HDR_OPT_CHECK",
@@ -1138,6 +1149,7 @@ int detection_option_node_evaluate(detection_option_tree_node_t \
*node, detection case RULE_OPTION_TYPE_TCP_WIN:
case RULE_OPTION_TYPE_TTL:
case RULE_OPTION_TYPE_URILEN:
+ case RULE_OPTION_TYPE_ETHER_TYPE:
#ifdef DYNAMIC_PLUGIN
case RULE_OPTION_TYPE_HDR_OPT_CHECK:
case RULE_OPTION_TYPE_PREPROCESSOR:
diff --git a/src/detection-plugins/sp_ether_type.c \
b/src/detection-plugins/sp_ether_type.c new file mode 100644
index 0000000..926864c
--- /dev/null
+++ b/src/detection-plugins/sp_ether_type.c
@@ -0,0 +1,361 @@
+/*
+** Copyright (C) 2011 Joshua Kinard <kumba@gentoo.org>
+**
+** 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+/* $Id$ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <sys/types.h>
+#include <stdlib.h>
+#include <ctype.h>
+
+#include "sf_types.h"
+#include "rules.h"
+#include "treenodes.h"
+#include "decode.h"
+#include "plugbase.h"
+#include "parser.h"
+#include "util.h"
+#include "snort_debug.h"
+#include "plugin_enum.h"
+#include "sp_ether_type.h"
+
+#include "snort.h"
+#include "profiler.h"
+#ifdef PERF_PROFILING
+PreprocStats etherTypePerfStats;
+extern PreprocStats ruleOTNEvalPerfStats;
+#endif
+
+#include "sfhashfcn.h"
+#include "detection_options.h"
+
+
+/**
+ * EtherTypeHash - Hash function for ether_type.
+ * @data: pointer to EtherTypeData.
+ *
+ * Returns a uint32_t representing the hash.
+ */
+uint32_t EtherTypeHash(void *data)
+{
+ uint32_t a, b, c;
+ EtherTypeData *etd = (EtherTypeData *)data;
+
+ a = etd->value;
+ b = etd->operator;
+ c = RULE_OPTION_TYPE_ETHER_TYPE;
+ final(a, b, c);
+
+ return c;
+}
+
+/**
+ * EtherTypeCompare - Comparator function for ether_type.
+ * @l: pointer to EtherTypeData (left side).
+ * @r: pointer to EtherTypeData (right side).
+ *
+ * Returns the comparison result of the two data structures.
+ */
+int EtherTypeCompare(void *l, void *r)
+{
+ EtherTypeData *left = (EtherTypeData *)l;
+ EtherTypeData *right = (EtherTypeData *)r;
+
+ if (!left)
+ return (!right ? DETECTION_OPTION_EQUAL :
+ DETECTION_OPTION_NOT_EQUAL);
+
+ if (!right)
+ return (!left ? DETECTION_OPTION_EQUAL :
+ DETECTION_OPTION_NOT_EQUAL);
+
+ if (left->value == right->value)
+ return DETECTION_OPTION_NOT_EQUAL;
+
+ if (left->operator == right->operator)
+ return DETECTION_OPTION_NOT_EQUAL;
+
+ return DETECTION_OPTION_EQUAL;
+}
+
+/**
+ * EtherTypeSetup - Setup function for ether_type.
+ *
+ * Links the 'ether_type' keyword to its initialization function.
+ * Returns void.
+ */
+void EtherTypeSetup(void)
+{
+ /* Map the keyword to an initialization/processing function */
+ RegisterRuleOption("ether_type", EtherTypeInit, NULL, OPT_TYPE_DETECTION, NULL);
+
+#ifdef PERF_PROFILING
+ RegisterPreprocessorProfile("ether_type", ðerTypePerfStats, 3, \
&ruleOTNEvalPerfStats); +#endif
+
+ DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN,"Plugin: EtherType Initialized\n"););
+}
+
+/**
+ * EtherTypeInit - Initialization function for ether_type.
+ * @data: pointer to EtherTypeData (as char *).
+ * @otn: pointer to OptTreeNode structure.
+ * @protocol: integer value representing the transport-layer protocol.
+ *
+ * Attaches the rule option data to the appropriate data structure and links
+ * in the evaluator function to the function pointer list. Returns void.
+ */
+void EtherTypeInit(char *data, OptTreeNode *otn, int protocol)
+{
+ OptFpList *fpl;
+ EtherTypeData *etd;
+ void *etd_dup;
+
+ /* Rule must be an 'eth' rule to use this rule option */
+ if (protocol != ETH_II_FRAME)
+ FatalError("Error at %s:%d: 'ether_type' can only be used with "
+ "an 'eth' rule.\n", file_name, file_line);
+
+ /* Allocate the data structure. */
+ etd = (EtherTypeData *)SnortAlloc(sizeof(EtherTypeData));
+
+ /* Parse the keyword's parameters and configure the data structure. */
+ EtherTypeParse(data, etd);
+
+ /* Check for a duplicate entry in the otn. */
+ if (add_detection_option(RULE_OPTION_TYPE_ETHER_TYPE,
+ (void *)etd, &etd_dup) == DETECTION_OPTION_EQUAL)
+ {
+ free(etd);
+ etd = (EtherTypeData *)etd_dup;
+ }
+
+ /*
+ * Set the ds_list for the first ether_type check for a rule. This
+ * is needed for the high-speed rule optimization.
+ */
+ if (!otn->ds_list[PLUGIN_ETHER_TYPE])
+ otn->ds_list[PLUGIN_ETHER_TYPE] = etd;
+
+ /*
+ * Finally, attach the option's detection function to the rule's detection
+ * function pointer list
+ */
+ fpl = AddOptFuncToList(EtherTypeEval, otn);
+ fpl->type = RULE_OPTION_TYPE_ETHER_TYPE;
+ fpl->context = (void *)etd;
+}
+
+/**
+ * EtherTypeParse - Parsing function for ether_type.
+ * @data: pointer to EtherTypeData (as char *).
+ * @otn: pointer to OptTreeNode structure.
+ *
+ * Parses the rule option's parameter list and fills in the EtherTypeData
+ * structure. Returns void.
+ */
+void EtherTypeParse(char *data, EtherTypeData *etd)
+{
+ uint32_t etype;
+
+ if (!etd || !data)
+ FatalError("Error at %s:%d: Unable to parse the 'ether_type' "
+ "parameters.\n", file_name, file_line);
+
+ /* Skip any leading whitespace. */
+ while(isspace((int)*data)) data++;
+
+ /* Parse the parameter string. */
+ if (*data == '!')
+ {
+ etd->operator = ETHER_TYPE_NOT_EQUAL;
+ data++;
+ }
+ else if (*data == '>')
+ {
+ etd->operator = ETHER_TYPE_GT;
+ data++;
+ }
+ else if (*data == '<')
+ {
+ etd->operator = ETHER_TYPE_LT;
+ data++;
+ }
+ else
+ {
+ etd->operator = ETHER_TYPE_EQUAL;
+ }
+
+ /* Check to see if the parameter is numeric or a string. */
+ if(isdigit((int)*data))
+ {
+ char *endptr;
+
+ etype = strtoul(data, &endptr, 0);
+
+ if (*endptr || etype < ETHER_TYPE_MIN_VALUE || etype > UINT16_MAX)
+ FatalError("Error at %s:%d: The value passed to 'ether_type' "
+ "is invalid or out of range.\n", file_name, file_line);
+ }
+ else
+ {
+ /* Lookup the string name and get its corresponding value. */
+ etype = etype_lookup(data);
+
+ if (etype == ETHER_TYPE_LOOKUP_ERROR)
+ FatalError("Error at %s:%d: The name passed to 'ether_type' "
+ "is invalid.\n", file_name, file_line);
+ }
+ etd->value = (uint16_t)etype;
+
+ return;
+}
+
+/**
+ * EtherTypeEval - Evaluation function for ether_type.
+ * @data: pointer to EtherTypeData (as char *).
+ * @p: pointer to Packet structure.
+ *
+ * Evaluates the rule option against the packet pointed to by 'p'. Returns
+ * either DETECTION_OPTION_MATCH or DETECTION_OPTION_NO_MATCH.
+ */
+int EtherTypeEval(void *data, Packet *p)
+{
+ EtherTypeData *etd = (EtherTypeData *)data;
+ int rval = DETECTION_OPTION_NO_MATCH;
+ PROFILE_VARS;
+
+ if(!p->eh || !etd)
+ return rval;
+
+ PREPROC_PROFILE_START(etherTypePerfStats);
+
+ switch (etd->operator)
+ {
+ case ETHER_TYPE_EQUAL:
+ if (etd->value == p->eth_type)
+ rval = DETECTION_OPTION_MATCH;
+ break;
+
+ case ETHER_TYPE_NOT_EQUAL:
+ if (etd->value != p->eth_type)
+ rval = DETECTION_OPTION_MATCH;
+ break;
+
+ case ETHER_TYPE_LT:
+ if (etd->value < p->eth_type)
+ rval = DETECTION_OPTION_MATCH;
+ break;
+
+ case ETHER_TYPE_GT:
+ if (etd->value > p->eth_type)
+ rval = DETECTION_OPTION_MATCH;
+ break;
+
+ default:
+ break;
+ }
+
+ PREPROC_PROFILE_END(etherTypePerfStats);
+
+ return rval;
+}
+
+
+
+/* Helper functions used by other areas of Snort. */
+
+/**
+ * GetEthTypes - creates a map of ethernet types set in a rule.
+ * @data: pointer to EtherTypeData (as char *).
+ * @etype_array: pointer to array of ethernet type mappings.
+ * @eta_size: size of the array pointed at by etype_array.
+ */
+int GetEthTypes(void *data, uint8_t *etype_array, int eta_size)
+{
+ EtherTypeData *etd = (EtherTypeData *)data;
+ int i;
+
+ if (!etype_array || (eta_size < NUM_ETH_TYPES))
+ return -1;
+
+ /* Eth type not set, so include them all. */
+ if (!data)
+ {
+ memset(etype_array, 1, eta_size);
+ return 0;
+ }
+
+ memset(etype_array, 0, eta_size);
+
+ switch (etd->operator)
+ {
+ case ETHER_TYPE_EQUAL:
+ etype_array[etd->value] = 1;
+ break;
+
+ case ETHER_TYPE_NOT_EQUAL:
+ for (i = 0; i < etd->value; i++)
+ etype_array[i] = 1;
+ for (i += 1; i < NUM_ETH_TYPES; i++)
+ etype_array[i] = 1;
+ break;
+
+ case ETHER_TYPE_LT:
+ for (i = 0; i < etd->value; i++)
+ etype_array[i] = 1;
+ break;
+
+ case ETHER_TYPE_GT:
+ for (i = (etd->value + 1); i < NUM_ETH_TYPES; i++)
+ etype_array[i] = 1;
+ break;
+
+ default:
+ return -1;
+ }
+
+ return 0;
+}
+
+#if 0
+/**
+ * GetOtnEthType - extract the ether_type field from an otn.
+ * @otn: pointer to OptTreeNode.
+ *
+ * Not used at present. Mimiced from ip_proto, so maybe one day?
+ */
+int GetOtnEthType(OptTreeNode *otn)
+{
+ EtherTypeData *etd;
+
+ if (!otn)
+ return -1;
+
+ etd = (EtherTypeData *)otn->ds_list[PLUGIN_ETHER_TYPE];
+
+ if (etd && (etd->operator == ETHER_TYPE_EQUAL))
+ return (int)etd->value;
+
+ return -1;
+}
+#endif
diff --git a/src/detection-plugins/sp_ether_type.h \
b/src/detection-plugins/sp_ether_type.h new file mode 100644
index 0000000..5a16280
--- /dev/null
+++ b/src/detection-plugins/sp_ether_type.h
@@ -0,0 +1,125 @@
+/*
+** Copyright (C) 2011 Joshua Kinard <kumba@gentoo.org>
+**
+** 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+/* $Id$ */
+#ifndef __SP_ETHER_TYPE_H__
+#define __SP_ETHER_TYPE_H__
+
+/* Operator definitions for sctp_payload_id. */
+#define ETHER_TYPE_EQUAL 0x01
+#define ETHER_TYPE_NOT_EQUAL 0x02
+#define ETHER_TYPE_LT 0x03
+#define ETHER_TYPE_GT 0x04
+
+/* The error value if an ethertype lookup fails. */
+#define ETHER_TYPE_LOOKUP_ERROR 0xdeadbac9
+
+/* Smallest numeric ethertype that we will accept. */
+#define ETHER_TYPE_MIN_VALUE 0x0600
+
+
+/* EtherType data structure. */
+typedef struct _EtherTypeData
+{
+ uint16_t value;
+ uint8_t operator;
+} EtherTypeData;
+
+
+/**
+ * struct _ethertype_map_t.
+ * @name: char pointer for the etherype name.
+ * @etype: uint16_t ethertype value.
+ */
+typedef struct _ethertype_map_t {
+ const char *name;
+ const uint32_t etype;
+} ethertype_map_t;
+
+
+/*
+ * Mapping of Ethertype name -> value.
+ *
+ * This is a short list. It should encompass the most
+ * common ethernet frame types that one might ever see
+ * on a network.
+ */
+static const ethertype_map_t etype_table[] =
+{
+ {"xerox", 0x0600}, /* Xerox NS IDP */
+ {"ipv4", 0x0800}, /* IP version 4 */
+ {"x75", 0x0801}, /* X.75 Internet */
+ {"nbs", 0x0802}, /* NBS Internet */
+ {"ecma", 0x0803}, /* ECMA Internet */
+ {"chaos", 0x0804}, /* CHAOSNet */
+ {"x25", 0x0805}, /* X.25 Level 3 */
+ {"arp", 0x0806}, /* Address Resolution Protocol */
+ {"rarp", 0x0835}, /* Reverse ARP */
+ {"wol", 0x0842}, /* Wake On LAN */
+ {"ax25", 0x08ff}, /* AX.25 over Ethernet (G8BPQ) */
+ {"decnet", 0x6003}, /* DECnet DNA */
+ {"apple", 0x809b}, /* Appletalk */
+ {"aarp", 0x80f3}, /* Appletalk ARP */
+ {"vlan", 0x8100}, /* VLAN Tagged 802.1q */
+ {"netbeui", 0x8191}, /* NetBEUI */
+ {"ipx", 0x8137}, /* Novell IPX/SPX */
+ {"snmp", 0x814c}, /* SNMP over Ethernet */
+ {"ipv6", 0x86dd}, /* IP version 6 */
+ {"slow", 0x8809}, /* Slow Protocols */
+ {"ppp", 0x880b}, /* Point-to-Point Protocol */
+ {"mpls", 0x8847}, /* MPLS Unicast */
+ {"pppoed", 0x8863}, /* PPP over Ethernet Discovery */
+ {"pppoes", 0x8864}, /* PPP over Ethernet Session */
+ {"eapol", 0x888e}, /* EAPOL (EAP over LAN), IEEE 802.1x */
+ {"aoe", 0x88a2}, /* ATA over Ethernet */
+ {"lldp", 0x88cc}, /* Logical Link Discovery Protocol */
+ {"fcoe", 0x8906}, /* FibreChannel over Ethernet */
+ {"fip", 0x8914}, /* FCoE Initialization Protocol */
+ {"tte", 0x891d}, /* TTEthernet */
+ {"loop", 0x9000}, /* Loopback */
+};
+
+
+/**
+ * etype_lookup - ethertype lookup function.
+ * @name: ethertype name to look up in etype_table.
+ */
+static const inline uint32_t etype_lookup(const char *name)
+{
+ const ethertype_map_t *e = etype_table;
+
+ for (; e->name != NULL; ++e)
+ if (strcmp(e->name, name) == 0)
+ return e->etype;
+
+ return ETHER_TYPE_LOOKUP_ERROR;
+}
+
+
+/* Prototypes. */
+uint32_t EtherTypeHash(void *data);
+int EtherTypeCompare(void *l, void *r);
+void EtherTypeSetup(void);
+void EtherTypeInit(char *data, OptTreeNode *otn, int protocol);
+void EtherTypeParse(char *data, EtherTypeData *etd);
+int EtherTypeEval(void *data, Packet *p);
+int GetEthTypes(void *data, uint8_t *etype_array, int eta_size);
+int GetOtnEthType(OptTreeNode *otn);
+
+#endif /* __SP_ETHER_TYPE_H__ */
diff --git a/src/dynamic-plugins/sf_engine/sf_snort_packet.h \
b/src/dynamic-plugins/sf_engine/sf_snort_packet.h index 1541af9..bcdeab9 100644
--- a/src/dynamic-plugins/sf_engine/sf_snort_packet.h
+++ b/src/dynamic-plugins/sf_engine/sf_snort_packet.h
@@ -530,6 +530,7 @@ typedef struct _SFSnortPacket
const uint8_t *ip_frag_start;
const uint8_t *ip4_options_data;
const uint8_t *tcp_options_data;
+ const uint8_t *ethernet_data;
void *stream_session_ptr;
void *fragmentation_tracking_ptr;
@@ -573,6 +574,8 @@ typedef struct _SFSnortPacket
uint16_t normalized_payload_size;
uint16_t actual_ip_length;
uint16_t outer_ip_payload_size;
+ uint16_t eth_payload_size;
+ uint16_t eth_type;
uint16_t ip_fragment_offset;
uint16_t ip_frag_length;
diff --git a/src/fpcreate.c b/src/fpcreate.c
index f19a8c2..6e57d85 100644
--- a/src/fpcreate.c
+++ b/src/fpcreate.c
@@ -50,6 +50,7 @@
#include "sp_icmp_type_check.h"
#include "sp_file_data.h"
#include "sp_ip_proto.h"
+#include "sp_ether_type.h"
#include "plugin_enum.h"
#include "util.h"
#include "rules.h"
@@ -88,6 +89,8 @@ enum
static void fpAddIpProtoOnlyRule(SF_LIST **, OptTreeNode *);
static void fpRegIpProto(uint8_t *, OptTreeNode *);
+static void fpAddRawEthIIRule(SF_LIST **, OptTreeNode *);
+static void fpRegEthType(uint8_t *, OptTreeNode *otn);
static int fpCreatePortGroups(SnortConfig *, rule_port_tables_t *);
static void fpDeletePortGroup(void *);
static void fpDeletePMX(void *data);
@@ -392,49 +395,49 @@ static int ServiceMapAddOtn(srmm_table_t *srmm, int proto, char \
*servicename, Op SFGHASH * to_srv; /* to srv service rule map */
SFGHASH * to_cli; /* to cli service rule map */
- if( !servicename )
+ if (!servicename || !otn)
return 0;
- if(!otn )
- return 0;
-
- if( proto == IPPROTO_TCP)
- {
- to_srv = srmm->tcp_to_srv;
- to_cli = srmm->tcp_to_cli;
- }
- else if( proto == IPPROTO_UDP)
- {
- to_srv = srmm->udp_to_srv;
- to_cli = srmm->udp_to_cli;
- }
- else if( proto == IPPROTO_ICMP )
- {
- to_srv = srmm->icmp_to_srv;
- to_cli = srmm->icmp_to_cli;
- }
- else if( proto == ETHERNET_TYPE_IP )
+ switch (proto)
{
- to_srv = srmm->tcp_to_srv;
- to_cli = srmm->ip_to_cli;
- }
- else
- {
- return 0;
- }
+ case IPPROTO_TCP:
+ to_srv = srmm->tcp_to_srv;
+ to_cli = srmm->tcp_to_cli;
+ break;
- if( fpOtnFlowToServer(otn) )
- {
- ServiceMapAddOtnRaw( to_srv, servicename, otn );
- }
- else if( fpOtnFlowToClient(otn) )
- {
- ServiceMapAddOtnRaw( to_cli, servicename, otn );
+ case IPPROTO_UDP:
+ to_srv = srmm->udp_to_srv;
+ to_cli = srmm->udp_to_cli;
+ break;
+
+ case IPPROTO_ICMP:
+ to_srv = srmm->icmp_to_srv;
+ to_cli = srmm->icmp_to_cli;
+ break;
+
+ case ETHERNET_TYPE_IP:
+ to_srv = srmm->ip_to_srv;
+ to_cli = srmm->ip_to_cli;
+ break;
+
+ case ETH_II_FRAME:
+ to_srv = srmm->eth_to_srv;
+ to_cli = srmm->eth_to_cli;
+ break;
+
+ default:
+ return 0;
+ break;
}
+
+ if (fpOtnFlowToServer(otn))
+ ServiceMapAddOtnRaw(to_srv, servicename, otn);
+ else if (fpOtnFlowToClient(otn))
+ ServiceMapAddOtnRaw(to_cli, servicename, otn);
else /* else add to both sides */
{
- ServiceMapAddOtnRaw( to_srv, servicename, otn );
- ServiceMapAddOtnRaw( to_cli, servicename, otn );
+ ServiceMapAddOtnRaw(to_srv, servicename, otn);
+ ServiceMapAddOtnRaw(to_cli, servicename, otn);
}
return 0;
@@ -455,6 +458,12 @@ int prmFindRuleGroupIp(PORT_RULE_MAP *prm, int ip_proto, \
PORT_GROUP **ip_group, return prmFindRuleGroup( prm, ip_proto, -1, &src, ip_group, \
gen); }
+int prmFindRuleGroupEth(PORT_RULE_MAP *prm, int eth_type, PORT_GROUP **eth_group, \
PORT_GROUP ** gen) +{
+ PORT_GROUP *src;
+ return prmFindRuleGroup( prm, eth_type, -1, &src, eth_group, gen);
+}
+
int prmFindRuleGroupIcmp(PORT_RULE_MAP *prm, int type, PORT_GROUP **type_group, \
PORT_GROUP ** gen) {
PORT_GROUP *src;
@@ -2060,6 +2069,13 @@ static int fpCreateRuleMaps(SnortConfig *sc, \
rule_port_tables_t *p)
if (fpCreateInitRuleMap(sc->prmIcmpRTNX, p->icmp_src, p->icmp_dst, \
p->icmp_anyany, p->icmp_nocontent)) return -1;
+ sc->prmEthRTNX = prmNewMap();
+ if (sc->prmEthRTNX == NULL)
+ return 1;
+
+ if (fpCreateInitRuleMap(sc->prmEthRTNX, p->eth_src, p->eth_dst, p->eth_anyany, \
p->eth_nocontent)) + return -1;
+
return 0;
}
@@ -2091,6 +2107,12 @@ static void fpFreeRuleMaps(SnortConfig *sc)
free(sc->prmIcmpRTNX);
sc->prmIcmpRTNX = NULL;
}
+
+ if (sc->prmEthRTNX != NULL)
+ {
+ free(sc->prmEthRTNX);
+ sc->prmEthRTNX = NULL;
+ }
}
static int fpGetFinalPattern(FastPatternConfig *fp, PatternMatchData *pmd,
@@ -2099,11 +2121,8 @@ static int fpGetFinalPattern(FastPatternConfig *fp, \
PatternMatchData *pmd, char *pattern;
int bytes;
- if ((fp == NULL) || (pmd == NULL)
- || (ret_pattern == NULL) || (ret_bytes == NULL))
- {
+ if ((!fp) || (!pmd) || (!ret_pattern) || (!ret_bytes))
return -1;
- }
pattern = pmd->pattern_buf;
bytes = pmd->pattern_size;
@@ -2427,6 +2446,22 @@ static int fpCreatePortObject2PortGroup(SnortConfig *sc, \
PortObject2 *po, PortOb
fpRegIpProto(sc->ip_proto_array, otn);
}
+ else if (otn->proto == ETH_II_FRAME)
+ {
+ /*
+ * If there is only one detection option and it is
+ * ether_type, then it will be evaluated at decode
+ * time instead of detection time.
+ */
+ if (otn->ds_list[PLUGIN_ETHER_TYPE] &&
+ (otn->num_detection_opts == 1))
+ {
+ fpAddRawEthIIRule(sc->eth_type_only_lists, otn);
+ continue;
+ }
+
+ fpRegEthType(sc->eth_type_array, otn);
+ }
if (fpAddPortGroupRule(pg, otn, fp) != 0)
continue;
@@ -2676,6 +2711,45 @@ static int fpCreatePortGroups(SnortConfig *sc, \
rule_port_tables_t *p)
//LogMessage("fpcreate: calling PortObjectFree2(po2), line = %d\n",__LINE__ );
PortObject2Free(po2);
+ /* ETH */
+ po2 = PortObject2Dup(p->eth_anyany);
+ if (po2 == NULL)
+ FatalError("Could not create a PortObject version 2 for eth-any-any \
rules\n!"); +
+ if (!fpDetectSplitAnyAny(fp))
+ add_any_any = po2;
+
+ if (fpDetectGetDebugPrintRuleGroupBuildDetails(fp))
+ LogMessage("\nETH-SRC ");
+
+ if (fpCreatePortTablePortGroups(sc, p->eth_src, add_any_any))
+ {
+ LogMessage("fpCreatePorTablePortGroups failed-eth_src\n");
+ return -1;
+ }
+
+ if (fpDetectGetDebugPrintRuleGroupBuildDetails(fp))
+ LogMessage("\nETH-DST ");
+
+ if (fpCreatePortTablePortGroups(sc, p->eth_dst, add_any_any))
+ {
+ LogMessage("fpCreatePorTablePortGroups failed-eth_dst\n");
+ return -1;
+ }
+
+ if (fpDetectGetDebugPrintRuleGroupBuildDetails(fp))
+ LogMessage("\nETH-ANYANY ");
+
+ if (fpCreatePortObject2PortGroup(sc, po2, 0))
+ {
+ LogMessage("fpCreatePorTablePortGroups failed-eth any-any\n");
+ return -1;
+ }
+
+ p->eth_anyany->data = po2->data;
+ p->eth_anyany->data_free = fpDeletePortGroup;
+ po2->data = 0;
+ PortObject2Free(po2);
return 0;
}
@@ -2716,7 +2790,8 @@ void fpWalkOtns(int enabled, OtnWalkFcn fcn)
continue;
if ((rtn->proto == IPPROTO_TCP) || (rtn->proto == IPPROTO_UDP)
- || (rtn->proto == IPPROTO_ICMP) || (rtn->proto == ETHERNET_TYPE_IP))
+ || (rtn->proto == IPPROTO_ICMP) || (rtn->proto == ETHERNET_TYPE_IP)
+ || (rtn->proto == ETH_II_FRAME))
{
//do operation
if ( enabled && (otn->rule_state != RULE_STATE_ENABLED) )
@@ -2753,7 +2828,8 @@ static int fpCreateServiceMaps(SnortConfig *sc)
rtn = getRtnFromOtn(otn, policyId);
if (rtn && ((rtn->proto == IPPROTO_TCP) || (rtn->proto == IPPROTO_UDP)
- || (rtn->proto == IPPROTO_ICMP) || (rtn->proto == \
ETHERNET_TYPE_IP))) + || (rtn->proto == IPPROTO_ICMP) || \
(rtn->proto == ETHERNET_TYPE_IP) + || (rtn->proto == \
ETH_II_FRAME))) {
//do operation
@@ -2820,6 +2896,22 @@ void fpBuildServicePortGroupByServiceOtnList(SFGHASH *p, char \
*srvc, SF_LIST *li continue;
}
}
+ else if (otn->proto == ETH_II_FRAME)
+ {
+ /*
+ * If there is only one detection option and it is
+ * ether_type, then it will be evaluated at decode
+ * time instead of detection time.
+ *
+ * These will have already been added when adding
+ * port groups
+ */
+ if (otn->ds_list[PLUGIN_ETHER_TYPE] &&
+ (otn->num_detection_opts == 1))
+ {
+ continue;
+ }
+ }
if (fpAddPortGroupRule(pg, otn, fp) != 0)
continue;
@@ -2940,6 +3032,11 @@ static void fpCreateServiceMapPortGroups(SnortConfig *sc)
sc->srmmTable->ip_to_srv, fp);
fpBuildServicePortGroups(sc->spgmmTable->ip_to_cli, sc->sopgTable->ip_to_srv,
sc->srmmTable->ip_to_cli, fp);
+
+ fpBuildServicePortGroups(sc->spgmmTable->eth_to_srv, sc->sopgTable->eth_to_srv,
+ sc->srmmTable->eth_to_srv, fp);
+ fpBuildServicePortGroups(sc->spgmmTable->eth_to_cli, sc->sopgTable->eth_to_srv,
+ sc->srmmTable->eth_to_cli, fp);
}
PORT_GROUP * fpGetServicePortGroupByOrdinal(sopg_table_t *sopg, int proto, int dir, \
int16_t proto_ordinal) @@ -2987,6 +3084,14 @@ PORT_GROUP * \
fpGetServicePortGroupByOrdinal(sopg_table_t *sopg, int proto, int d
break;
+ case ETH_II_FRAME:
+ if (dir == TO_SERVER)
+ pg = sopg->eth_to_srv[proto_ordinal];
+ else
+ pg = sopg->eth_to_cli[proto_ordinal];
+
+ break;
+
default:
break;
}
@@ -3279,6 +3384,10 @@ void fpShowEventStats(SnortConfig *sc)
LogMessage("\n");
LogMessage("** IP Event Stats --\n");
prmShowEventStats(sc->prmIpRTNX);
+
+ LogMessage("\n");
+ LogMessage("** ETH II Event Stats --\n");
+ prmShowEventStats(sc->prmEthRTNX);
}
static void fpAddIpProtoOnlyRule(SF_LIST **ip_proto_only_lists, OptTreeNode *otn)
@@ -3338,7 +3447,64 @@ static void fpRegIpProto(uint8_t *ip_proto_array, OptTreeNode \
*otn)
FatalError("%s(%d) Error getting ip protocols\n", __FILE__, __LINE__);
for (i = 0; i < NUM_IP_PROTOS; i++)
- if (ip_protos[i]) ip_proto_array[i] = 1;
+ if (ip_protos[i])
+ ip_proto_array[i] = 1;
+}
+
+static void fpAddRawEthIIRule(SF_LIST **eth_type_only_lists, OptTreeNode *otn)
+{
+ uint8_t etypes[NUM_ETH_TYPES];
+ uint32_t i;
+
+ if (!otn->ds_list[PLUGIN_ETHER_TYPE] || (otn->num_detection_opts != 1))
+ return;
+
+ if (GetEthTypes(otn->ds_list[PLUGIN_ETHER_TYPE], etypes, sizeof(etypes)) != 0)
+ FatalError("Error at %s:%d: Failed to get ethernet types\n",
+ file_name, file_line);
+
+ for (i = 0; i < NUM_ETH_TYPES; i++)
+ {
+ OptTreeNode *dup;
+
+ if (etypes[i])
+ {
+ if (!eth_type_only_lists[i])
+ {
+ eth_type_only_lists[i] = sflist_new();
+ if (!eth_type_only_lists[i])
+ FatalError("Error at %s:%d: Could not allocate memory for "
+ "ether_type array\n", file_name, file_line);
+ }
+
+ /* Search for duplicates. */
+ for (dup = (OptTreeNode *)sflist_first(eth_type_only_lists[i]);
+ dup != NULL;
+ dup = (OptTreeNode *)sflist_next(eth_type_only_lists[i]))
+ {
+ if (dup == otn)
+ return;
+ }
+
+ if (sflist_add_head(eth_type_only_lists[i], otn) != 0)
+ FatalError("Error at %s:%d: Failed to add otn to ether_type \
array\n", + file_name, file_line);
+ }
+ }
+}
+
+static void fpRegEthType(uint8_t *eth_type_array, OptTreeNode *otn)
+{
+ uint8_t etypes[NUM_ETH_TYPES];
+ uint32_t i;
+
+ if (GetEthTypes(otn->ds_list[PLUGIN_ETHER_TYPE], etypes, sizeof(etypes)) != 0)
+ FatalError("Error at %s:%d: Failed to get ethernet types\n",
+ file_name, file_line);
+
+ for (i = 0; i < NUM_ETH_TYPES; i++)
+ if (etypes[i])
+ eth_type_array[i] = 1;
}
const char * PatternRawToContent(const char *pattern, int pattern_len)
diff --git a/src/fpcreate.h b/src/fpcreate.h
index 4161700..6e26790 100644
--- a/src/fpcreate.h
+++ b/src/fpcreate.h
@@ -137,6 +137,9 @@ typedef struct
SFGHASH * ip_to_srv;
SFGHASH * ip_to_cli;
+ SFGHASH * eth_to_srv;
+ SFGHASH * eth_to_cli;
+
} srmm_table_t;
/*
@@ -156,6 +159,9 @@ typedef struct
PORT_GROUP *ip_to_srv[MAX_PROTOCOL_ORDINAL];
PORT_GROUP *ip_to_cli[MAX_PROTOCOL_ORDINAL];
+ PORT_GROUP *eth_to_srv[MAX_PROTOCOL_ORDINAL];
+ PORT_GROUP *eth_to_cli[MAX_PROTOCOL_ORDINAL];
+
} sopg_table_t;
#endif
@@ -184,6 +190,7 @@ int prmFindRuleGroupTcp(PORT_RULE_MAP *, int, int, PORT_GROUP **, \
PORT_GROUP **, int prmFindRuleGroupUdp(PORT_RULE_MAP *, int, int, PORT_GROUP **, \
PORT_GROUP **, PORT_GROUP **); int prmFindRuleGroupIp(PORT_RULE_MAP *, int, \
PORT_GROUP **, PORT_GROUP **); int prmFindRuleGroupIcmp(PORT_RULE_MAP *, int, \
PORT_GROUP **, PORT_GROUP **); +int prmFindRuleGroupEth(PORT_RULE_MAP *, int, \
PORT_GROUP **, PORT_GROUP **);
int fpSetDetectSearchMethod(FastPatternConfig *, char *);
void fpSetDetectSearchOpt(FastPatternConfig *, int flag);
diff --git a/src/fpdetect.c b/src/fpdetect.c
index dde84d5..ba787ff 100644
--- a/src/fpdetect.c
+++ b/src/fpdetect.c
@@ -103,7 +103,7 @@ static inline int fpEvalHeaderIcmp(Packet *p, OTNX_MATCH_DATA *);
static inline int fpEvalHeaderTcp(Packet *p, OTNX_MATCH_DATA *);
static inline int fpEvalHeaderUdp(Packet *p, OTNX_MATCH_DATA *);
static inline int fpEvalHeaderSW(PORT_GROUP *port_group, Packet *p,
- int check_ports, char ip_rule, OTNX_MATCH_DATA *);
+ int check_ports, uint8_t rule_type, OTNX_MATCH_DATA \
*); static int rule_tree_match (void* id, void * tree, int index, void * data, void \
*neg_list ); int fpAddMatch( OTNX_MATCH_DATA *omd_local, OTNX *otnx, int pLen, \
OptTreeNode *otn); static inline int fpAddSessionAlert(Packet *p, OptTreeNode *otn, \
int alerted); @@ -1044,6 +1044,7 @@ void printRuleFmt1( OptTreeNode * otn )
else if( rtn->proto== IPPROTO_UDP )LogMessage("udp ");
else if( rtn->proto== IPPROTO_ICMP )LogMessage("icmp ");
else if( rtn->proto== ETHERNET_TYPE_IP)LogMessage("ip ");
+ else if( rtn->proto== ETH_II_FRAME )LogMessage("eth ");
LogMessage("gid:%u sid:%5u ", otn->sigInfo.generator,otn->sigInfo.id);
@@ -1075,7 +1076,8 @@ void printRuleFmt1( OptTreeNode * otn )
** PORT_GROUP * - the port group to inspect
** Packet * - the packet to inspect
** int - whether src/dst ports should be checked (udp/tcp or icmp)
-** char - whether the rule is an IP rule (change the packet payload \
pointer) +** uint8_t - what the rule type is (other for TCP/UDP/etc, IP, or \
ETH_II). +** This sets the packet payload pointer appropriately.
**
** FORMAL OUTPUTS
** int - 0 for failed pattern match
@@ -1083,7 +1085,7 @@ void printRuleFmt1( OptTreeNode * otn )
**
*/
static inline int fpEvalHeaderSW(PORT_GROUP *port_group, Packet *p,
- int check_ports, char ip_rule, OTNX_MATCH_DATA *omd)
+ int check_ports, uint8_t rule_type, OTNX_MATCH_DATA *omd)
{
RULE_NODE *rnWalk;
void * so;
@@ -1099,7 +1101,7 @@ static inline int fpEvalHeaderSW(PORT_GROUP *port_group, Packet \
*p, FastPatternConfig *fp = snort_conf->fast_pattern_config;
PROFILE_VARS;
- if (ip_rule)
+ if (rule_type == SW_RULE_TYPE_IP)
{
/* Set the packet payload pointers to that of IP,
** since this is an IP rule. */
@@ -1127,9 +1129,19 @@ static inline int fpEvalHeaderSW(PORT_GROUP *port_group, \
Packet *p, }
}
}
+ else if (rule_type == SW_RULE_TYPE_ETH)
+ {
+ if (p->eth_data)
+ {
+ p->data = p->eth_data;
+ p->dsize = p->eth_dsize;
+ p->packet_flags |= PKT_ETH_II_RULE;
+ }
+ }
else
{
p->packet_flags &= ~PKT_IP_RULE;
+ p->packet_flags &= ~PKT_ETH_II_RULE;
}
/*
@@ -1348,7 +1360,7 @@ static inline int fpEvalHeaderSW(PORT_GROUP *port_group, Packet \
*p, }
#ifdef GRE
- if (ip_rule && p->outer_ip_data)
+ if ((rule_type == SW_RULE_TYPE_IP) && p->outer_ip_data)
{
/* Evaluate again with the inner IPs */
p->iph = p->inner_iph;
@@ -1370,7 +1382,7 @@ static inline int fpEvalHeaderSW(PORT_GROUP *port_group, Packet \
*p, #ifdef PPM_MGR /* Tag only used with PPM right now */
fp_eval_header_sw_reset_ip:
#endif
- if (ip_rule)
+ if (rule_type == SW_RULE_TYPE_IP)
{
/* Set the data & dsize back to original values. */
p->iph = tmp_iph;
@@ -1442,19 +1454,19 @@ static inline int fpEvalHeaderUdp(Packet *p, OTNX_MATCH_DATA \
*omd)
if (dst != NULL)
{
- if (fpEvalHeaderSW(dst, p, 1, 0, omd))
+ if (fpEvalHeaderSW(dst, p, 1, SW_RULE_TYPE_OTHER, omd))
return 1;
}
if (src != NULL)
{
- if (fpEvalHeaderSW(src, p, 1, 0, omd))
+ if (fpEvalHeaderSW(src, p, 1, SW_RULE_TYPE_OTHER, omd))
return 1;
}
if (gen != NULL)
{
- if (fpEvalHeaderSW(gen, p, 1, 0, omd))
+ if (fpEvalHeaderSW(gen, p, 1, SW_RULE_TYPE_OTHER, omd))
return 1;
}
@@ -1526,19 +1538,19 @@ static inline int fpEvalHeaderTcp(Packet *p, OTNX_MATCH_DATA \
*omd)
if (dst != NULL)
{
- if (fpEvalHeaderSW(dst, p, 1, 0, omd))
+ if (fpEvalHeaderSW(dst, p, 1, SW_RULE_TYPE_OTHER, omd))
return 1;
}
if (src != NULL)
{
- if (fpEvalHeaderSW(src, p, 1, 0, omd))
+ if (fpEvalHeaderSW(src, p, 1, SW_RULE_TYPE_OTHER, omd))
return 1;
}
if (gen != NULL)
{
- if(fpEvalHeaderSW(gen, p, 1, 0, omd))
+ if(fpEvalHeaderSW(gen, p, 1, SW_RULE_TYPE_OTHER, omd))
return 1;
}
@@ -1566,13 +1578,13 @@ static inline int fpEvalHeaderIcmp(Packet *p, OTNX_MATCH_DATA \
*omd)
if (type != NULL)
{
- if (fpEvalHeaderSW(type, p, 0, 0, omd))
+ if (fpEvalHeaderSW(type, p, 0, SW_RULE_TYPE_OTHER, omd))
return 1;
}
if (gen != NULL)
{
- if (fpEvalHeaderSW(gen, p, 0, 0, omd))
+ if (fpEvalHeaderSW(gen, p, 0, SW_RULE_TYPE_OTHER, omd))
return 1;
}
@@ -1596,13 +1608,43 @@ static inline int fpEvalHeaderIp(Packet *p, int ip_proto, \
OTNX_MATCH_DATA *omd)
if (ip_group != NULL)
{
- if (fpEvalHeaderSW(ip_group, p, 0, 1, omd))
+ if (fpEvalHeaderSW(ip_group, p, 0, SW_RULE_TYPE_IP, omd))
return 1;
}
if (gen != NULL)
{
- if (fpEvalHeaderSW(gen, p, 0, 1, omd))
+ if (fpEvalHeaderSW(gen, p, 0, SW_RULE_TYPE_IP, omd))
+ return 1;
+ }
+
+ return fpFinalSelectEvent(omd, p);
+}
+
+/*
+** fpEvalHeaderEth::
+*/
+static inline int fpEvalHeaderEth(Packet *p, int eth_type, OTNX_MATCH_DATA *omd)
+{
+ PORT_GROUP *gen = NULL, *eth_group = NULL;
+
+ if (!prmFindRuleGroupEth(snort_conf->prmEthRTNX, eth_type, ð_group, &gen))
+ return 0;
+
+ if(fpDetectGetDebugPrintNcRules(snort_conf->fast_pattern_config))
+ LogMessage("fpEvalHeaderEth: eth_group=%p, gen=%p\n", (void*)eth_group, \
(void*)gen); +
+ InitMatchInfo(omd);
+
+ if (eth_group)
+ {
+ if (fpEvalHeaderSW(eth_group, p, 0, SW_RULE_TYPE_ETH, omd))
+ return 1;
+ }
+
+ if (gen)
+ {
+ if (fpEvalHeaderSW(gen, p, 0, SW_RULE_TYPE_ETH, omd))
return 1;
}
@@ -1620,9 +1662,10 @@ static inline int fpEvalHeaderIp(Packet *p, int ip_proto, \
OTNX_MATCH_DATA *omd)
** process the both that particular ruleset and the IP ruleset
** with in the fpEvalHeader for that protocol. If the protocol
** is not TCP, UDP, or ICMP, we just process the packet against
-** the IP rules at the end of the fpEvalPacket routine. Since
-** we are using a setwise methodology for snort rules, both the
-** network layer rules and the transport layer rules are done
+** any IP or ETH rules at the end of the fpEvalPacket routine.
+**
+** Since we are using a setwise methodology for snort rules, both
+** the network layer rules and the transport layer rules are done
** at the same time. While this is not the best for modularity,
** it is the best for performance, which is what we are working
** on currently.
@@ -1636,86 +1679,99 @@ static inline int fpEvalHeaderIp(Packet *p, int ip_proto, \
OTNX_MATCH_DATA *omd)
*/
int fpEvalPacket(Packet *p)
{
- int ip_proto = GET_IPH_PROTO(p);
OTNX_MATCH_DATA *omd = snort_conf->omd;
- /* Run UDP rules against the UDP header of Teredo packets */
- if ( p->udph && (p->proto_bits & (PROTO_BIT__TEREDO | PROTO_BIT__GTP)) )
+ if (IPH_IS_VALID(p))
{
- uint16_t tmp_sp = p->sp;
- uint16_t tmp_dp = p->dp;
- const UDPHdr *tmp_udph = p->udph;
- const uint8_t *tmp_data = p->data;
- uint16_t tmp_dsize = p->dsize;
+ int ip_proto = GET_IPH_PROTO(p);
- if (p->outer_udph)
+ /* Run UDP rules against the UDP header of Teredo packets */
+ if ( p->udph && (p->proto_bits & (PROTO_BIT__TEREDO | PROTO_BIT__GTP)) )
{
- p->udph = p->outer_udph;
- }
- p->sp = ntohs(p->udph->uh_sport);
- p->dp = ntohs(p->udph->uh_dport);
- p->data = (const uint8_t *)p->udph + UDP_HEADER_LEN;
- if (p->outer_ip_dsize > UDP_HEADER_LEN)
- p->dsize = p->outer_ip_dsize - UDP_HEADER_LEN;
-
- fpEvalHeaderUdp(p, omd);
-
- p->sp = tmp_sp;
- p->dp = tmp_dp;
- p->udph = tmp_udph;
- p->data = tmp_data;
- p->dsize = tmp_dsize;
- }
-
- switch(ip_proto)
- {
- case IPPROTO_TCP:
- DEBUG_WRAP(DebugMessage(DEBUG_DETECT,
- "Detecting on TcpList\n"););
+ uint16_t tmp_sp = p->sp;
+ uint16_t tmp_dp = p->dp;
+ const UDPHdr *tmp_udph = p->udph;
+ const uint8_t *tmp_data = p->data;
+ uint16_t tmp_dsize = p->dsize;
- if(p->tcph == NULL)
+ if (p->outer_udph)
{
- ip_proto = -1;
- break;
+ p->udph = p->outer_udph;
}
+ p->sp = ntohs(p->udph->uh_sport);
+ p->dp = ntohs(p->udph->uh_dport);
+ p->data = (const uint8_t *)p->udph + UDP_HEADER_LEN;
+ if (p->outer_ip_dsize > UDP_HEADER_LEN)
+ p->dsize = p->outer_ip_dsize - UDP_HEADER_LEN;
+
+ fpEvalHeaderUdp(p, omd);
+
+ p->sp = tmp_sp;
+ p->dp = tmp_dp;
+ p->udph = tmp_udph;
+ p->data = tmp_data;
+ p->dsize = tmp_dsize;
+ }
- return fpEvalHeaderTcp(p, omd);
+ switch(ip_proto)
+ {
+ case IPPROTO_TCP:
+ DEBUG_WRAP(DebugMessage(DEBUG_DETECT,
+ "Detecting on TcpList\n"););
- case IPPROTO_UDP:
- DEBUG_WRAP(DebugMessage(DEBUG_DETECT,
- "Detecting on UdpList\n"););
+ if(p->tcph == NULL)
+ {
+ ip_proto = -1;
+ break;
+ }
- if(p->udph == NULL)
- {
- ip_proto = -1;
- break;
- }
+ return fpEvalHeaderTcp(p, omd);
+
+ case IPPROTO_UDP:
+ DEBUG_WRAP(DebugMessage(DEBUG_DETECT,
+ "Detecting on UdpList\n"););
+
+ if(p->udph == NULL)
+ {
+ ip_proto = -1;
+ break;
+ }
- return fpEvalHeaderUdp(p, omd);
+ return fpEvalHeaderUdp(p, omd);
#ifdef SUP_IP6
- case IPPROTO_ICMPV6:
+ case IPPROTO_ICMPV6:
#endif
- case IPPROTO_ICMP:
- DEBUG_WRAP(DebugMessage(DEBUG_DETECT,
- "Detecting on IcmpList\n"););
+ case IPPROTO_ICMP:
+ DEBUG_WRAP(DebugMessage(DEBUG_DETECT,
+ "Detecting on IcmpList\n"););
- if(p->icmph == NULL)
- {
- ip_proto = -1;
+ if(p->icmph == NULL)
+ {
+ ip_proto = -1;
+ break;
+ }
+
+ return fpEvalHeaderIcmp(p, omd);
+
+ default:
break;
- }
+ }
- return fpEvalHeaderIcmp(p, omd);
+ /*
+ ** No Match on TCP/UDP, Do IP
+ */
+ return fpEvalHeaderIp(p, ip_proto, omd);
+ }
+ else if (p->eh)
+ {
+ /* Raw Ethernet II Frame */
+ int eth_type = (int)p->eth_type;
- default:
- break;
+ return fpEvalHeaderEth(p, eth_type, omd);
}
- /*
- ** No Match on TCP/UDP, Do IP
- */
- return fpEvalHeaderIp(p, ip_proto, omd);
+ return 0;
}
void fpEvalIpProtoOnlyRules(SF_LIST **ip_proto_only_lists, Packet *p)
@@ -1748,3 +1804,32 @@ void fpEvalIpProtoOnlyRules(SF_LIST **ip_proto_only_lists, \
Packet *p) }
}
+void fpEvalEtherTypeOnlyRules(SF_LIST **eth_type_only_lists, Packet *p)
+{
+ if (p && p->eh)
+ {
+ SF_LIST *l = eth_type_only_lists[p->eth_type];
+ OptTreeNode *otn;
+
+ /* If list is NULL, sflist_first returns NULL */
+ for (otn = (OptTreeNode *)sflist_first(l);
+ otn != NULL;
+ otn = (OptTreeNode *)sflist_next(l))
+ {
+ if (fpEvalRTN(getRuntimeRtnFromOtn(otn), p, 0))
+ {
+ SnortEventqAdd(otn->sigInfo.generator,
+ otn->sigInfo.id,
+ otn->sigInfo.rev,
+ otn->sigInfo.class_id,
+ otn->sigInfo.priority,
+ otn->sigInfo.message,
+ (void *)NULL);
+ if (RULE_TYPE__PASS == getRuntimeRtnFromOtn(otn)->type)
+ {
+ p->packet_flags |= PKT_PASS_RULE;
+ }
+ }
+ }
+ }
+}
diff --git a/src/fpdetect.h b/src/fpdetect.h
index e92928c..3a39f7b 100644
--- a/src/fpdetect.h
+++ b/src/fpdetect.h
@@ -43,6 +43,17 @@
#define REBUILD_FLAGS (PKT_REBUILT_FRAG | PKT_REBUILT_STREAM)
/*
+ * Prior to adding ethernet II frame detection, fpEvalHeaderSW took a
+ * boolean value to state if it was an IP-only rule so that the appropriate
+ * pointers could be setup. Rather than add an extra argument to the
+ * fpEvalHeaderSW function, we'll just change the 'char ip_rule' argument
+ * into 'uint8_t rule_type' to select between different rule types.
+ */
+#define SW_RULE_TYPE_OTHER 0x00 /* TCP/UDP/ICMP */
+#define SW_RULE_TYPE_IP 0x01 /* IP */
+#define SW_RULE_TYPE_ETH 0x02 /* ETH_II */
+
+/*
** This is the only function that is needed to do an
** inspection on a packet.
*/
@@ -98,6 +109,7 @@ void OtnxMatchDataFree(OTNX_MATCH_DATA *);
int fpAddMatch( OTNX_MATCH_DATA *omd_local, OTNX *otnx, int pLen,
OptTreeNode *otn);
void fpEvalIpProtoOnlyRules(SF_LIST **, Packet *);
+void fpEvalEtherTypeOnlyRules(SF_LIST **, Packet *);
#define TO_SERVER 1
#define TO_CLIENT 0
diff --git a/src/parser.c b/src/parser.c
index 805262e..5c83633 100644
--- a/src/parser.c
+++ b/src/parser.c
@@ -80,6 +80,7 @@
#include "sp_preprocopt.h"
#include "detection-plugins/sp_icmp_type_check.h"
#include "detection-plugins/sp_ip_proto.h"
+#include "detection-plugins/sp_ether_type.h"
#include "detection-plugins/sp_pattern_match.h"
#include "sf_vartable.h"
#include "ipv6_port.h"
@@ -130,6 +131,7 @@
#define RULE_PROTO_OPT__TCP "tcp"
#define RULE_PROTO_OPT__UDP "udp"
#define RULE_PROTO_OPT__ICMP "icmp"
+#define RULE_PROTO_OPT__ETH "eth"
#define RULE_DIR_OPT__DIRECTIONAL "->"
#define RULE_DIR_OPT__BIDIRECTIONAL "<>"
@@ -462,6 +464,7 @@ static rule_count_t tcpCnt;
static rule_count_t udpCnt;
static rule_count_t icmpCnt;
static rule_count_t ipCnt;
+static rule_count_t ethCnt;
rule_index_map_t *ruleIndexMap = NULL; /* rule index -> sid:gid map */
@@ -921,6 +924,7 @@ SnortConfig * ParseSnortConf(void)
sc->rate_filter_config = RateFilter_ConfigNew();
sc->detection_filter_config = DetectionFilterConfigNew();
sc->ip_proto_only_lists = (SF_LIST **)SnortAlloc(NUM_IP_PROTOS * sizeof(SF_LIST \
*)); + sc->eth_type_only_lists = (SF_LIST **)SnortAlloc(NUM_ETH_TYPES * \
sizeof(SF_LIST *));
/* We're not going to parse rules on the first pass */
parse_rules = 0;
@@ -1208,6 +1212,7 @@ static void DumpRuleChains(RuleListNode *rule_lists)
while (rule != NULL)
{
+ DumpChain(rule->name, rule->mode, ETH_II_FRAME);
DumpChain(rule->name, rule->mode, ETHERNET_TYPE_IP);
DumpChain(rule->name, rule->mode, IPPROTO_TCP);
DumpChain(rule->name, rule->mode, IPPROTO_UDP);
@@ -1313,43 +1318,55 @@ static int FinishPortListRule(rule_port_tables_t \
*port_tables, RuleTreeNode *rtn PortObject *ncObject;
rule_count_t *prc;
- /* Select the Target PortTable for this rule, based on protocol, src/dst
- * dir, and if there is rule content */
- if (proto == IPPROTO_TCP)
- {
- dstTable = port_tables->tcp_dst;
- srcTable = port_tables->tcp_src;
- aaObject = port_tables->tcp_anyany;
- ncObject = port_tables->tcp_nocontent;
- prc = &tcpCnt;
- }
- else if (proto == IPPROTO_UDP)
- {
- dstTable = port_tables->udp_dst;
- srcTable = port_tables->udp_src;
- aaObject = port_tables->udp_anyany;
- ncObject = port_tables->udp_nocontent;
- prc = &udpCnt;
- }
- else if (proto == IPPROTO_ICMP)
- {
- dstTable = port_tables->icmp_dst;
- srcTable = port_tables->icmp_src;
- aaObject = port_tables->icmp_anyany;
- ncObject = port_tables->icmp_nocontent;
- prc = &icmpCnt;
- }
- else if (proto == ETHERNET_TYPE_IP)
- {
- dstTable = port_tables->ip_dst;
- srcTable = port_tables->ip_src;
- aaObject = port_tables->ip_anyany;
- ncObject = port_tables->ip_nocontent;
- prc = &ipCnt;
- }
- else
- {
- return -1;
+ /*
+ * Select the Target PortTable for this rule, based on protocol, src/dst
+ * dir, and if there is rule content
+ */
+ switch (proto)
+ {
+ case IPPROTO_TCP:
+ dstTable = port_tables->tcp_dst;
+ srcTable = port_tables->tcp_src;
+ aaObject = port_tables->tcp_anyany;
+ ncObject = port_tables->tcp_nocontent;
+ prc = &tcpCnt;
+ break;
+
+ case IPPROTO_UDP:
+ dstTable = port_tables->udp_dst;
+ srcTable = port_tables->udp_src;
+ aaObject = port_tables->udp_anyany;
+ ncObject = port_tables->udp_nocontent;
+ prc = &udpCnt;
+ break;
+
+ case IPPROTO_ICMP:
+ dstTable = port_tables->icmp_dst;
+ srcTable = port_tables->icmp_src;
+ aaObject = port_tables->icmp_anyany;
+ ncObject = port_tables->icmp_nocontent;
+ prc = &icmpCnt;
+ break;
+
+ case ETHERNET_TYPE_IP:
+ dstTable = port_tables->ip_dst;
+ srcTable = port_tables->ip_src;
+ aaObject = port_tables->ip_anyany;
+ ncObject = port_tables->ip_nocontent;
+ prc = &ipCnt;
+ break;
+
+ case ETH_II_FRAME:
+ dstTable = port_tables->eth_dst;
+ srcTable = port_tables->eth_src;
+ aaObject = port_tables->eth_anyany;
+ ncObject = port_tables->eth_nocontent;
+ prc = ðCnt;
+ break;
+
+ default:
+ return -1;
+ break;
}
/* Count rules with both src and dst specific ports */
@@ -1464,6 +1481,12 @@ static int FinishPortListRule(rule_port_tables_t *port_tables, \
RuleTreeNode *rtn PortObjectAddRule(aaObject, rim_index);
prc->aa++;
}
+ else if (proto == ETH_II_FRAME)
+ {
+ PortObjectAddRule(port_tables->eth_anyany, rim_index);
+ ethCnt.aa++;
+ prc->aa++;
+ }
else
{
/* For other protocols-tcp/udp/icmp add to the any any group */
@@ -3237,6 +3260,10 @@ static int GetRuleProtocol(char *proto_str)
{
return ETHERNET_TYPE_IP;
}
+ else if (strcasecmp(proto_str, RULE_PROTO_OPT__ETH) == 0)
+ {
+ return ETH_II_FRAME;
+ }
else
{
/* If we've gotten here, we have a protocol string we didn't recognize
@@ -5026,7 +5053,8 @@ int CheckRuleStates(SnortConfig *sc)
}
if ((rtn->proto == IPPROTO_TCP) || (rtn->proto == IPPROTO_UDP) ||
- (rtn->proto == IPPROTO_ICMP) || (rtn->proto == ETHERNET_TYPE_IP))
+ (rtn->proto == IPPROTO_ICMP) || (rtn->proto == ETHERNET_TYPE_IP) ||
+ (rtn->proto == ETH_II_FRAME))
{
//do operation
if ( otn->sigInfo.shared )
@@ -5996,6 +6024,7 @@ static void InitParser(void)
memset(&udpCnt, 0, sizeof(udpCnt));
memset(&ipCnt, 0, sizeof(ipCnt));
memset(&icmpCnt, 0, sizeof(icmpCnt));
+ memset(ðCnt, 0, sizeof(ethCnt));
port_list_free(&port_list);
memset(&port_list, 0, sizeof(port_list));
@@ -6085,12 +6114,12 @@ void ParseRules(SnortConfig *sc)
PortTablesFinish(sc->port_tables, sc->fast_pattern_config);
LogMessage("+-------------------[Rule Port \
Counts]---------------------------------------\n");
- LogMessage("|%8s%8s%8s%8s%8s\n", " ", "tcp", "udp", "icmp", "ip");
- LogMessage("|%8s%8u%8u%8u%8u\n", "src", tcpCnt.src, udpCnt.src, icmpCnt.src, \
ipCnt.src);
- LogMessage("|%8s%8u%8u%8u%8u\n", "dst", tcpCnt.dst, udpCnt.dst, icmpCnt.dst, \
ipCnt.dst);
- LogMessage("|%8s%8u%8u%8u%8u\n", "any", tcpCnt.aa, udpCnt.aa, icmpCnt.aa, \
ipCnt.aa);
- LogMessage("|%8s%8u%8u%8u%8u\n", "nc", tcpCnt.nc, udpCnt.nc, icmpCnt.nc, \
ipCnt.nc);
- LogMessage("|%8s%8u%8u%8u%8u\n", "s+d", tcpCnt.sd, udpCnt.sd, icmpCnt.sd, \
ipCnt.sd); + LogMessage("|%8s%8s%8s%8s%8s%8s\n", " ", "tcp", "udp", "icmp", "ip", \
"eth"); + LogMessage("|%8s%8u%8u%8u%8u%8u\n", "src", tcpCnt.src, udpCnt.src, \
icmpCnt.src, ipCnt.src, ethCnt.src); + LogMessage("|%8s%8u%8u%8u%8u%8u\n", "dst", \
tcpCnt.dst, udpCnt.dst, icmpCnt.dst, ipCnt.dst, ethCnt.dst); + \
LogMessage("|%8s%8u%8u%8u%8u%8u\n", "any", tcpCnt.aa, udpCnt.aa, icmpCnt.aa, \
ipCnt.aa, ethCnt.aa); + LogMessage("|%8s%8u%8u%8u%8u%8u\n", "nc", tcpCnt.nc, \
udpCnt.nc, icmpCnt.nc, ipCnt.nc, ethCnt.nc); + LogMessage("|%8s%8u%8u%8u%8u%8u\n", \
"s+d", tcpCnt.sd, udpCnt.sd, icmpCnt.sd, ipCnt.sd, ethCnt.sd);
LogMessage("+----------------------------------------------------------------------------\n");
///print_rule_index_map( ruleIndexMap );
@@ -9468,16 +9497,27 @@ static void ParseRule(SnortConfig *sc, SnortPolicy *p, char \
*args, case IPPROTO_TCP:
sc->ip_proto_array[IPPROTO_TCP] = 1;
break;
+
case IPPROTO_UDP:
sc->ip_proto_array[IPPROTO_UDP] = 1;
break;
+
case IPPROTO_ICMP:
sc->ip_proto_array[IPPROTO_ICMP] = 1;
sc->ip_proto_array[IPPROTO_ICMPV6] = 1;
break;
+
case ETHERNET_TYPE_IP:
/* This will be set via ip_protos */
break;
+
+ case ETH_II_FRAME:
+ /*
+ * This will configure sc->eth_type_array instead, via a call
+ * into GetEthTypes in src/detection-plugins/esp_ether_type.c.
+ */
+ break;
+
default:
ParseError("Bad protocol: %s", toks[0]);
break;
@@ -11483,24 +11523,29 @@ static rule_port_tables_t * PortTablesNew(void)
/* No content rule objects */
rpt->tcp_nocontent = PortObjectNew();
if (rpt->tcp_nocontent == NULL)
- FatalError("ParseRulesFile nocontent PortObjectNew() failed\n");
+ FatalError("ParseRulesFile tcp nocontent PortObjectNew() failed\n");
PortObjectAddPortAny(rpt->tcp_nocontent);
rpt->udp_nocontent = PortObjectNew();
if (rpt->udp_nocontent == NULL)
- FatalError("ParseRulesFile nocontent PortObjectNew() failed\n");
+ FatalError("ParseRulesFile udp nocontent PortObjectNew() failed\n");
PortObjectAddPortAny(rpt->udp_nocontent);
rpt->icmp_nocontent = PortObjectNew();
if (rpt->icmp_nocontent == NULL)
- FatalError("ParseRulesFile nocontent PortObjectNew() failed\n");
+ FatalError("ParseRulesFile icmp nocontent PortObjectNew() failed\n");
PortObjectAddPortAny(rpt->icmp_nocontent);
rpt->ip_nocontent = PortObjectNew();
if (rpt->ip_nocontent == NULL)
- FatalError("ParseRulesFile nocontent PortObjectNew() failed\n");
+ FatalError("ParseRulesFile ip nocontent PortObjectNew() failed\n");
PortObjectAddPortAny(rpt->ip_nocontent);
+ rpt->eth_nocontent = PortObjectNew();
+ if (rpt->eth_nocontent == NULL)
+ FatalError("ParseRulesFile eth nocontent PortObjectNew() failed\n");
+ PortObjectAddPortAny(rpt->eth_nocontent);
+
/* Create the Any-Any Port Objects for each protocol */
rpt->tcp_anyany = PortObjectNew();
if (rpt->tcp_anyany == NULL)
@@ -11522,6 +11567,11 @@ static rule_port_tables_t * PortTablesNew(void)
FatalError("ParseRulesFile ip PortObjectNew() failed\n");
PortObjectAddPortAny(rpt->ip_anyany);
+ rpt->eth_anyany = PortObjectNew();
+ if (rpt->eth_anyany == NULL)
+ FatalError("ParseRulesFile eth PortObjectNew() failed\n");
+ PortObjectAddPortAny(rpt->eth_anyany);
+
/* Create the tcp Rules PortTables */
rpt->tcp_src = PortTableNew();
if (rpt->tcp_src == NULL)
@@ -11558,6 +11608,15 @@ static rule_port_tables_t * PortTablesNew(void)
if (rpt->ip_dst == NULL)
FatalError("ParseRulesFile ip-dst PortTableNew() failed\n");
+ /* Create the eth Rules PortTables */
+ rpt->eth_src = PortTableNew();
+ if (rpt->eth_src == NULL)
+ FatalError("ParseRulesFile eth-src PortTableNew() failed\n");
+
+ rpt->eth_dst = PortTableNew();
+ if (rpt->eth_dst == NULL)
+ FatalError("ParseRulesFile eth-dst PortTableNew() failed\n");
+
/*
* someday these could be read from snort.conf, something like...
* 'config portlist: large-rule-count <val>'
@@ -11570,6 +11629,8 @@ static rule_port_tables_t * PortTablesNew(void)
rpt->icmp_dst->pt_lrc= DEFAULT_LARGE_RULE_GROUP;
rpt->ip_src->pt_lrc = DEFAULT_LARGE_RULE_GROUP;
rpt->ip_dst->pt_lrc = DEFAULT_LARGE_RULE_GROUP;
+ rpt->eth_src->pt_lrc = DEFAULT_LARGE_RULE_GROUP;
+ rpt->eth_dst->pt_lrc = DEFAULT_LARGE_RULE_GROUP;
return rpt;
}
@@ -11620,14 +11681,27 @@ static void PortTablesFinish(rule_port_tables_t \
*port_tables, FastPatternConfig finish_portlist_table(fp, "ip src", \
port_tables->ip_src); finish_portlist_table(fp, "ip dst", port_tables->ip_dst);
+ /* ETH-SRC */
+ if (fpDetectGetDebugPrintRuleGroupsCompiled(fp))
+ {
+ LogMessage("ETH-Any-Any Port List\n");
+ PortObjectPrintEx(port_tables->eth_anyany,
+ rule_index_map_print_index);
+ }
+
+ finish_portlist_table(fp, "eth src", port_tables->eth_src);
+ finish_portlist_table(fp, "eth dst", port_tables->eth_dst);
+
RuleListSortUniq(port_tables->tcp_anyany->rule_list);
RuleListSortUniq(port_tables->udp_anyany->rule_list);
RuleListSortUniq(port_tables->icmp_anyany->rule_list);
RuleListSortUniq(port_tables->ip_anyany->rule_list);
+ RuleListSortUniq(port_tables->eth_anyany->rule_list);
RuleListSortUniq(port_tables->tcp_nocontent->rule_list);
RuleListSortUniq(port_tables->udp_nocontent->rule_list);
RuleListSortUniq(port_tables->icmp_nocontent->rule_list);
RuleListSortUniq(port_tables->ip_nocontent->rule_list);
+ RuleListSortUniq(port_tables->eth_nocontent->rule_list);
}
void VarTablesFree(SnortConfig *sc)
@@ -11693,6 +11767,10 @@ void PortTablesFree(rule_port_tables_t *port_tables)
PortTableFree(port_tables->ip_src);
if (port_tables->ip_dst)
PortTableFree(port_tables->ip_dst);
+ if (port_tables->eth_src)
+ PortTableFree(port_tables->eth_src);
+ if (port_tables->eth_dst)
+ PortTableFree(port_tables->eth_dst);
if (port_tables->tcp_anyany)
PortObjectFree(port_tables->tcp_anyany);
@@ -11702,6 +11780,8 @@ void PortTablesFree(rule_port_tables_t *port_tables)
PortObjectFree(port_tables->icmp_anyany);
if (port_tables->ip_anyany)
PortObjectFree(port_tables->ip_anyany);
+ if (port_tables->eth_anyany)
+ PortObjectFree(port_tables->eth_anyany);
if (port_tables->tcp_nocontent)
PortObjectFree(port_tables->tcp_nocontent);
@@ -11711,6 +11791,8 @@ void PortTablesFree(rule_port_tables_t *port_tables)
PortObjectFree(port_tables->icmp_nocontent);
if (port_tables->ip_nocontent)
PortObjectFree(port_tables->ip_nocontent);
+ if (port_tables->eth_nocontent)
+ PortObjectFree(port_tables->eth_nocontent);
free(port_tables);
}
@@ -12241,7 +12323,8 @@ static void IntegrityCheckRules(SnortConfig *sc)
}
if ((rtn->proto == IPPROTO_TCP) || (rtn->proto == IPPROTO_UDP)
- || (rtn->proto == IPPROTO_ICMP) || (rtn->proto == \
ETHERNET_TYPE_IP)) + || (rtn->proto == IPPROTO_ICMP) || \
(rtn->proto == ETHERNET_TYPE_IP) + || (rtn->proto == \
ETH_II_FRAME)) {
//do operation
ofl_idx = otn->opt_func;
@@ -12255,9 +12338,7 @@ static void IntegrityCheckRules(SnortConfig *sc)
}
if(opt_func_count == 0)
- {
FatalError("Zero Length OTN List\n");
- }
//DEBUG_WRAP(DebugMessage(DEBUG_DETECT,"\n"););
}
diff --git a/src/plugbase.c b/src/plugbase.c
index f3a2100..4b12bd1 100644
--- a/src/plugbase.c
+++ b/src/plugbase.c
@@ -94,6 +94,7 @@
#include "detection-plugins/sp_base64_data.h"
#include "detection-plugins/sp_pkt_data.h"
#include "detection-plugins/sp_asn1.h"
+#include "detection-plugins/sp_ether_type.h"
#ifdef ENABLE_REACT
#include "detection-plugins/sp_react.h"
#endif
@@ -210,6 +211,7 @@ void RegisterRuleOptions(void)
SetupFTPBounce();
SetupUriLenCheck();
SetupCvs();
+ EtherTypeSetup();
}
/****************************************************************************
diff --git a/src/plugin_enum.h b/src/plugin_enum.h
index 6e897cd..f240a9e 100644
--- a/src/plugin_enum.h
+++ b/src/plugin_enum.h
@@ -62,6 +62,7 @@ enum {
PLUGIN_FLOWBIT,
PLUGIN_FILE_DATA,
PLUGIN_BASE64_DECODE,
+ PLUGIN_ETHER_TYPE,
PLUGIN_MAX /* sentinel value */
};
diff --git a/src/rule_option_types.h b/src/rule_option_types.h
index d1bbe61..9b31da6 100644
--- a/src/rule_option_types.h
+++ b/src/rule_option_types.h
@@ -64,7 +64,8 @@ typedef enum _option_type_t
RULE_OPTION_TYPE_TCP_SEQ,
RULE_OPTION_TYPE_TCP_WIN,
RULE_OPTION_TYPE_TTL,
- RULE_OPTION_TYPE_URILEN
+ RULE_OPTION_TYPE_URILEN,
+ RULE_OPTION_TYPE_ETHER_TYPE
#ifdef DYNAMIC_PLUGIN
,
RULE_OPTION_TYPE_HDR_OPT_CHECK,
diff --git a/src/sfutil/sfportobject.h b/src/sfutil/sfportobject.h
index 209228d..100482b 100644
--- a/src/sfutil/sfportobject.h
+++ b/src/sfutil/sfportobject.h
@@ -161,24 +161,27 @@ typedef struct _PortTable_s {
}PortTable;
-typedef struct {
+typedef struct _rule_port_tables_t {
PortTable * tcp_src, * tcp_dst;
PortTable * udp_src, * udp_dst;
PortTable * icmp_src,* icmp_dst;
PortTable * ip_src, * ip_dst;
+ PortTable * eth_src, * eth_dst;
PortObject * tcp_anyany;
PortObject * udp_anyany;
PortObject * icmp_anyany;
PortObject * ip_anyany;
+ PortObject * eth_anyany;
PortObject * tcp_nocontent;
PortObject * udp_nocontent;
PortObject * icmp_nocontent;
PortObject * ip_nocontent;
+ PortObject * eth_nocontent;
-}rule_port_tables_t;
+} rule_port_tables_t;
#define POPERR_NO_NAME 1
diff --git a/src/snort.c b/src/snort.c
index 6b3eeee..273a163 100644
--- a/src/snort.c
+++ b/src/snort.c
@@ -3810,9 +3810,9 @@ void SnortConfFree(SnortConfig *sc)
if ( sc->event_queue )
SnortEventqFree(sc->event_queue);
- if (sc->ip_proto_only_lists != NULL)
+ if (sc->ip_proto_only_lists)
{
- unsigned int j;
+ uint32_t j;
for (j = 0; j < NUM_IP_PROTOS; j++)
sflist_free_all(sc->ip_proto_only_lists[j], NULL);
@@ -3820,6 +3820,16 @@ void SnortConfFree(SnortConfig *sc)
free(sc->ip_proto_only_lists);
}
+ if (sc->eth_type_only_lists)
+ {
+ uint32_t j;
+
+ for (j = 0; j < NUM_ETH_TYPES; j++)
+ sflist_free_all(sc->eth_type_only_lists[j], NULL);
+
+ free(sc->eth_type_only_lists);
+ }
+
#if defined(SNORT_RELOAD) && !defined(WIN32)
FreePreprocReloadVerifyFuncList(sc->preproc_reload_verify_funcs);
#endif
diff --git a/src/snort.h b/src/snort.h
index ede94d1..882c33a 100644
--- a/src/snort.h
+++ b/src/snort.h
@@ -794,6 +794,9 @@ typedef struct _SnortConfig
SF_LIST **ip_proto_only_lists;
uint8_t ip_proto_array[NUM_IP_PROTOS];
+ SF_LIST **eth_type_only_lists;
+ uint8_t eth_type_array[NUM_ETH_TYPES];
+
int num_rule_types;
RuleListNode *rule_lists;
int evalOrder[RULE_TYPE__MAX + 1];
@@ -833,6 +836,7 @@ typedef struct _SnortConfig
* rules, or any combination. We process the uricontent 1st,
* then the content, and then the no content rules for udp/tcp
* and icmp, than we process the ip rules. */
+ PORT_RULE_MAP *prmEthRTNX;
PORT_RULE_MAP *prmIpRTNX;
PORT_RULE_MAP *prmTcpRTNX;
PORT_RULE_MAP *prmUdpRTNX;
------------------------------------------------------------------------------
Write once. Port to many.
Get the SDK and tools to simplify cross-platform app development. Create
new or port existing apps to sell to consumers worldwide. Explore the
Intel AppUpSM program developer opportunity. appdeveloper.intel.com/join
http://p.sf.net/sfu/intel-appdev
_______________________________________________
Snort-devel mailing list
Snort-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/snort-devel
Please visit http://blog.snort.org for the latest news about Snort!
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic