suricata
util-spm-bs.c
Go to the documentation of this file.
1 /* Copyright (C) 2007-2010 Open Information Security Foundation
2  *
3  * You can copy, redistribute or modify this Program under the terms of
4  * the GNU General Public License version 2 as published by the Free
5  * Software Foundation.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * version 2 along with this program; if not, write to the Free Software
14  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
15  * 02110-1301, USA.
16  */
17 
18 /**
19  * \file
20  *
21  * \author Victor Julien <victor@inliniac.net>
22  * \author Pablo Rincon Crespo <pablo.rincon.crespo@gmail.com>
23  *
24  * bs is a bruteforce search. It will try to search the pattern
25  * from all characters until the available text len is less
26  * than the length of the pattern. It needs no context but it
27  * time cost is not good.
28  */
29 
30 #include "suricata-common.h"
31 #include "suricata.h"
32 
33 #include "util-debug.h"
34 #include "util-spm-bs.h"
35 
36 /**
37  * \brief Basic search improved. Limits are better handled, so
38  * it doesn't start searches that wont fit in the remaining buffer
39  *
40  * Use libc's memmem if available.
41  *
42  * \param haystack pointer to the buffer to search in
43  * \param haystack_len length limit of the buffer
44  * \param needle pointer to the pattern we ar searching for
45  * \param needle_len length limit of the needle
46  *
47  * \retval ptr to start of the match; NULL if no match
48  */
49 uint8_t *BasicSearch(const uint8_t *haystack, uint32_t haystack_len, const uint8_t *needle, uint16_t needle_len)
50 {
51  SCEnter();
52 #ifdef HAVE_MEMMEM
53  return memmem(haystack, haystack_len, needle, needle_len);
54 #else
55  const uint8_t *h, *n;
56  const uint8_t *hmax = haystack + haystack_len;
57  const uint8_t *nmax = needle + needle_len;
58 
59  if (needle_len == 0 || needle_len > haystack_len) {
60  SCReturnPtr(NULL, "uint8_t");
61  }
62 
63  //PrintRawDataFp(stdout,needle,needle_len);
64 
65  //PrintRawDataFp(stdout,haystack,haystack_len);
66 
67  for (n = needle; nmax - n <= hmax - haystack; haystack++) {
68  if (*haystack != *n) {
69  continue;
70  }
71 
72  SCLogDebug("*haystack == *n, %c == %c", *haystack, *n);
73 
74  /* one byte needles */
75  if (needle_len == 1) {
76  SCReturnPtr((uint8_t *)haystack, "uint8_t");
77  }
78 
79  for (h = haystack+1, n++; nmax - n <= hmax - haystack; h++, n++) {
80  if (*h != *n) {
81  break;
82  }
83  SCLogDebug("*haystack == *n, %c == %c", *haystack, *n);
84  /* if we run out of needle we fully matched */
85  if (n == nmax - 1) {
86  SCReturnPtr((uint8_t *)haystack, "uint8_t");
87  }
88  }
89  n = needle;
90  }
91 
92  SCReturnPtr(NULL, "uint8_t");
93 #endif /* HAVE_MEMMEM */
94 }
95 
96 /**
97  * \brief Basic search case less
98  *
99  * \param haystack pointer to the buffer to search in
100  * \param haystack_len length limit of the buffer
101  * \param needle pointer to the pattern we ar searching for
102  * \param needle_len length limit of the needle
103  *
104  * \retval ptr to start of the match; NULL if no match
105  */
106 uint8_t *BasicSearchNocase(const uint8_t *haystack, uint32_t haystack_len, const uint8_t *needle, uint16_t needle_len)
107 {
108  const uint8_t *h, *n;
109  const uint8_t *hmax = haystack + haystack_len;
110  const uint8_t *nmax = needle + needle_len;
111 
112  if (needle_len == 0 || needle_len > haystack_len)
113  return NULL;
114 
115  for (n = needle; nmax - n <= hmax - haystack; haystack++) {
116  if (u8_tolower(*haystack) != u8_tolower(*n)) {
117  continue;
118  }
119  /* one byte needles */
120  if (needle_len == 1) {
121  return (uint8_t *)haystack;
122  }
123 
124  for (h = haystack+1, n++; nmax - n <= hmax - h ; h++, n++) {
125  if (u8_tolower(*h) != u8_tolower(*n)) {
126  break;
127  }
128  /* if we run out of needle we fully matched */
129  if (n == nmax - 1) {
130  return (uint8_t *)haystack;
131  }
132  }
133  n = needle;
134  }
135 
136  return NULL;
137 }
138 
140  const uint8_t *haystack, uint32_t haystack_len, const uint8_t *needle, uint16_t needle_len)
141 {
142  uint8_t *r = BasicSearchNocase(haystack, haystack_len, needle, needle_len);
143  if (r == NULL) {
144  return haystack_len;
145  }
146  return (uint32_t)(r - haystack);
147 }
SCLogDebug
#define SCLogDebug(...)
Definition: util-debug.h:282
u8_tolower
#define u8_tolower(c)
Definition: suricata-common.h:453
util-spm-bs.h
util-debug.h
BasicSearchNocase
uint8_t * BasicSearchNocase(const uint8_t *haystack, uint32_t haystack_len, const uint8_t *needle, uint16_t needle_len)
Basic search case less.
Definition: util-spm-bs.c:106
SCEnter
#define SCEnter(...)
Definition: util-debug.h:284
BasicSearch
uint8_t * BasicSearch(const uint8_t *haystack, uint32_t haystack_len, const uint8_t *needle, uint16_t needle_len)
Basic search improved. Limits are better handled, so it doesn't start searches that wont fit in the r...
Definition: util-spm-bs.c:49
SCReturnPtr
#define SCReturnPtr(x, type)
Definition: util-debug.h:300
suricata-common.h
suricata.h
SCBasicSearchNocaseIndex
uint32_t SCBasicSearchNocaseIndex(const uint8_t *haystack, uint32_t haystack_len, const uint8_t *needle, uint16_t needle_len)
Definition: util-spm-bs.c:139