// SPDX-License-Identifier: GPL-2.0-or-later /* * lib/ts_bm.c Boyer-Moore text search implementation * * Authors: Pablo Neira Ayuso <[email protected]> * * ========================================================================== * * Implements Boyer-Moore string matching algorithm: * * [1] A Fast String Searching Algorithm, R.S. Boyer and Moore. * Communications of the Association for Computing Machinery, * 20(10), 1977, pp. 762-772. * https://www.cs.utexas.edu/users/moore/publications/fstrpos.pdf * * [2] Handbook of Exact String Matching Algorithms, Thierry Lecroq, 2004 * http://www-igm.univ-mlv.fr/~lecroq/string/string.pdf * * Note: Since Boyer-Moore (BM) performs searches for matchings from right * to left, it's still possible that a matching could be spread over * multiple blocks, in that case this algorithm won't find any coincidence. * * If you're willing to ensure that such thing won't ever happen, use the * Knuth-Pratt-Morris (KMP) implementation instead. In conclusion, choose * the proper string search algorithm depending on your setting. * * Say you're using the textsearch infrastructure for filtering, NIDS or * any similar security focused purpose, then go KMP. Otherwise, if you * really care about performance, say you're classifying packets to apply * Quality of Service (QoS) policies, and you don't mind about possible * matchings spread over multiple fragments, then go BM. */ #include <linux/kernel.h> #include <linux/module.h> #include <linux/types.h> #include <linux/string.h> #include <linux/ctype.h> #include <linux/textsearch.h> /* Alphabet size, use ASCII */ #define ASIZE … #if 0 #define DEBUGP … #else #define DEBUGP(args, format...) … #endif struct ts_bm { … }; static unsigned int matchpat(const u8 *pattern, unsigned int patlen, const u8 *text, bool icase) { … } static unsigned int bm_find(struct ts_config *conf, struct ts_state *state) { … } static int subpattern(u8 *pattern, int i, int j, int g) { … } static void compute_prefix_tbl(struct ts_bm *bm, int flags) { … } static struct ts_config *bm_init(const void *pattern, unsigned int len, gfp_t gfp_mask, int flags) { … } static void *bm_get_pattern(struct ts_config *conf) { … } static unsigned int bm_get_pattern_len(struct ts_config *conf) { … } static struct ts_ops bm_ops = …; static int __init init_bm(void) { … } static void __exit exit_bm(void) { … } MODULE_DESCRIPTION(…) …; MODULE_LICENSE(…) …; module_init(…) …; module_exit(exit_bm);