"Fossies" - the Fresh Open Source Software Archive

Member "snort-2.9.17/src/detection-plugins/sp_byte_jump.c" (16 Oct 2020, 28537 Bytes) of package /linux/misc/snort-2.9.17.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "sp_byte_jump.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 2.9.16.1_vs_2.9.17.

    1 /* $Id$ */
    2 /*
    3  ** Copyright (C) 2014-2020 Cisco and/or its affiliates. All rights reserved.
    4  ** Copyright (C) 2002-2013 Sourcefire, Inc.
    5  ** Author: Martin Roesch
    6  **
    7  ** This program is free software; you can redistribute it and/or modify
    8  ** it under the terms of the GNU General Public License Version 2 as
    9  ** published by the Free Software Foundation.  You may not use, modify or
   10  ** distribute this program under any other version of the GNU General
   11  ** Public License.
   12  **
   13  ** This program is distributed in the hope that it will be useful,
   14  ** but WITHOUT ANY WARRANTY; without even the implied warranty of
   15  ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   16  ** GNU General Public License for more details.
   17  **
   18  ** You should have received a copy of the GNU General Public License
   19  ** along with this program; if not, write to the Free Software
   20  ** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
   21  */
   22 
   23 /* sp_byte_jump
   24  *
   25  * Purpose:
   26  *      Grab some number of bytes, convert them to their numeric
   27  *      representation, jump the doe_ptr up that many bytes (for
   28  *      further pattern matching/byte_testing).
   29  *
   30  *
   31  * Arguments:
   32  *      Required:
   33  *      <bytes_to_grab>: number of bytes to pick up from the packet
   34  *      <offset>: number of bytes into the payload to grab the bytes
   35  *      Optional:
   36  *      ["relative"]: offset relative to last pattern match
   37  *      ["big"]: process data as big endian (default)
   38  *      ["little"]: process data as little endian
   39  *      ["string"]: converted bytes represented as a string needing conversion
   40  *      ["hex"]: converted string data is represented in hexidecimal
   41  *      ["dec"]: converted string data is represented in decimal
   42  *      ["oct"]: converted string data is represented in octal
   43  *      ["align"]: round the number of converted bytes up to the next
   44  *                 32-bit boundry
   45  *      ["post_offset"]: number of bytes to adjust after applying
   46  *
   47  *   sample rules:
   48  *   alert udp any any -> any 32770:34000 (content: "|00 01 86 B8|"; \
   49  *       content: "|00 00 00 01|"; distance: 4; within: 4; \
   50  *       byte_jump: 4, 12, relative, align; \
   51  *       byte_test: 4, >, 900, 20, relative; \
   52  *       msg: "statd format string buffer overflow";)
   53  *
   54  * Effect:
   55  *
   56  *      Reads in the indicated bytes, converts them to an numeric
   57  *      representation and then jumps the doe_ptr up
   58  *      that number of bytes.  Returns 1 if the jump is in range (within the
   59  *      packet) and 0 if it's not.
   60  *
   61  * Comments:
   62  *
   63  * Any comments?
   64  *
   65  */
   66 
   67 #ifdef HAVE_CONFIG_H
   68 #include "config.h"
   69 #endif
   70 
   71 #include <sys/types.h>
   72 #include <stdlib.h>
   73 #include <ctype.h>
   74 #ifdef HAVE_STRINGS_H
   75 #include <strings.h>
   76 #endif
   77 #include <errno.h>
   78 
   79 #include "sf_types.h"
   80 #include "snort_bounds.h"
   81 #include "rules.h"
   82 #include "treenodes.h"
   83 #include "decode.h"
   84 #include "plugbase.h"
   85 #include "parser.h"
   86 #include "snort_debug.h"
   87 #include "util.h"
   88 #include "plugin_enum.h"
   89 #include "mstring.h"
   90 #include "byte_extract.h"
   91 #include "sp_byte_jump.h"
   92 #include "sp_byte_extract.h"
   93 #include "sp_byte_math.h"
   94 #include "sfhashfcn.h"
   95 
   96 #include "snort.h"
   97 #include "profiler.h"
   98 #ifdef PERF_PROFILING
   99 PreprocStats byteJumpPerfStats;
  100 extern PreprocStats ruleOTNEvalPerfStats;
  101 #endif
  102 
  103 #include "sfhashfcn.h"
  104 #include "detection_options.h"
  105 #include "detection_util.h"
  106 
  107 typedef struct _ByteJumpOverrideData
  108 {
  109     char *keyword;
  110     char *option;
  111     union
  112     {
  113         RuleOptOverrideFunc fptr;
  114         void *void_fptr;
  115     } fptr;
  116     struct _ByteJumpOverrideData *next;
  117 } ByteJumpOverrideData;
  118 
  119 ByteJumpOverrideData *byteJumpOverrideFuncs = NULL;
  120 
  121 static void ByteJumpOverride(char *keyword, char *option, RuleOptOverrideFunc roo_func);
  122 static void ByteJumpOverrideFuncsFree(void);
  123 static void ByteJumpInit(struct _SnortConfig *, char *, OptTreeNode *, int);
  124 static ByteJumpOverrideData * ByteJumpParse(char *, ByteJumpData *, OptTreeNode *);
  125 static void ByteJumpOverrideCleanup(int, void *);
  126 
  127 
  128 uint32_t ByteJumpHash(void *d)
  129 {
  130     uint32_t a,b,c;
  131     ByteJumpData *data = (ByteJumpData *)d;
  132 
  133     a = data->bytes_to_grab;
  134     b = data->offset;
  135     c = data->base;
  136 
  137     mix(a,b,c);
  138 
  139     a += (data->relative_flag << 24 |
  140           data->data_string_convert_flag << 16 |
  141           data->from_beginning_flag << 8 |
  142           data->align_flag);
  143     b += data->bitmask_val;
  144     c += data->multiplier;
  145 
  146     mix(a,b,c);
  147 
  148     a += RULE_OPTION_TYPE_BYTE_JUMP;
  149     b += data->post_offset;
  150     c += (data->endianess << 24 |
  151           data->offset_var << 16 |
  152           data->postoffset_var << 8 |
  153           data->from_end_flag);
  154 
  155     mix(a,b,c);
  156 
  157 #if (defined(__ia64) || defined(__amd64) || defined(_LP64))
  158     {
  159         /* Cleanup warning because of cast from 64bit ptr to 32bit int
  160          * warning on 64bit OSs */
  161         uint64_t ptr; /* Addresses are 64bits */
  162 
  163         ptr = (uint64_t) data->byte_order_func;
  164         a += (ptr >> 32);
  165         b += (ptr & 0xFFFFFFFF);
  166     }
  167 #else
  168     a += (uint32_t)data->byte_order_func;
  169 #endif
  170 
  171     final(a,b,c);
  172 
  173     return c;
  174 }
  175 
  176 int ByteJumpCompare(void *l, void *r)
  177 {
  178     ByteJumpData *left = (ByteJumpData *)l;
  179     ByteJumpData *right = (ByteJumpData *)r;
  180 
  181     if (!left || !right)
  182         return DETECTION_OPTION_NOT_EQUAL;
  183 
  184     if (( left->bytes_to_grab == right->bytes_to_grab) &&
  185         ( left->offset == right->offset) &&
  186         ( left->offset_var == right->offset_var) &&
  187         ( left->relative_flag == right->relative_flag) &&
  188         ( left->data_string_convert_flag == right->data_string_convert_flag) &&
  189         ( left->from_beginning_flag == right->from_beginning_flag) &&
  190         ( left->from_end_flag == right->from_end_flag) &&
  191         ( left->align_flag == right->align_flag) &&
  192         ( left->endianess == right->endianess) &&
  193         ( left->base == right->base) &&
  194         ( left->bitmask_val == right->bitmask_val) &&
  195         ( left->multiplier == right->multiplier) &&
  196         ( left->post_offset == right->post_offset) &&
  197         ( left->postoffset_var == right->postoffset_var) &&
  198         ( left->byte_order_func == right->byte_order_func))
  199     {
  200         return DETECTION_OPTION_EQUAL;
  201     }
  202 
  203     return DETECTION_OPTION_NOT_EQUAL;
  204 }
  205 
  206 static void ByteJumpOverride(char *keyword, char *option, RuleOptOverrideFunc roo_func)
  207 {
  208     ByteJumpOverrideData *new = SnortAlloc(sizeof(ByteJumpOverrideData));
  209 
  210     new->keyword = SnortStrdup(keyword);
  211     new->option = SnortStrdup(option);
  212     new->func = roo_func;
  213 
  214     new->next = byteJumpOverrideFuncs;
  215     byteJumpOverrideFuncs = new;
  216 }
  217 
  218 static void ByteJumpOverrideFuncsFree(void)
  219 {
  220     ByteJumpOverrideData *node = byteJumpOverrideFuncs;
  221 
  222     while (node != NULL)
  223     {
  224         ByteJumpOverrideData *tmp = node;
  225 
  226         node = node->next;
  227 
  228         if (tmp->keyword != NULL)
  229             free(tmp->keyword);
  230 
  231         if (tmp->option != NULL)
  232             free(tmp->option);
  233 
  234         free(tmp);
  235     }
  236 
  237     byteJumpOverrideFuncs = NULL;
  238 }
  239 
  240 /****************************************************************************
  241  *
  242  * Function: SetupByteJump()
  243  *
  244  * Purpose: Load 'er up
  245  *
  246  * Arguments: None.
  247  *
  248  * Returns: void function
  249  *
  250  ****************************************************************************/
  251 void SetupByteJump(void)
  252 {
  253     /* This list is only used during parsing */
  254     if (byteJumpOverrideFuncs != NULL)
  255         ByteJumpOverrideFuncsFree();
  256 
  257     /* map the keyword to an initialization/processing function */
  258     RegisterRuleOption("byte_jump", ByteJumpInit, ByteJumpOverride, OPT_TYPE_DETECTION, NULL);
  259     AddFuncToCleanExitList(ByteJumpOverrideCleanup, NULL);
  260     AddFuncToRuleOptParseCleanupList(ByteJumpOverrideFuncsFree);
  261 
  262 #ifdef PERF_PROFILING
  263     RegisterPreprocessorProfile("byte_jump", &byteJumpPerfStats, 3, &ruleOTNEvalPerfStats, NULL);
  264 #endif
  265 
  266     DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN,"Plugin: ByteJump Setup\n"););
  267 }
  268 
  269 
  270 /****************************************************************************
  271  *
  272  * Function: ByteJumpInit(char *, OptTreeNode *)
  273  *
  274  * Purpose: Generic rule configuration function.  Handles parsing the rule
  275  *          information and attaching the associated detection function to
  276  *          the OTN.
  277  *
  278  * Arguments: data => rule arguments/data
  279  *            otn => pointer to the current rule option list node
  280  *            protocol => protocol the rule is on (we don't care in this case)
  281  *
  282  * Returns: void function
  283  *
  284  ****************************************************************************/
  285 static void ByteJumpInit(struct _SnortConfig *sc, char *data, OptTreeNode *otn, int protocol)
  286 {
  287     ByteJumpData *idx;
  288     OptFpList *fpl;
  289     ByteJumpOverrideData *override;
  290     void *idx_dup;
  291 
  292     /* allocate the data structure and attach it to the
  293        rule's data struct list */
  294     idx = (ByteJumpData *) calloc(sizeof(ByteJumpData), sizeof(char));
  295 
  296     if(idx == NULL)
  297     {
  298         FatalError("%s(%d): Unable to allocate byte_jump data node\n",
  299                    file_name, file_line);
  300     }
  301 
  302     /* this is where the keyword arguments are processed and placed into the
  303        rule option's data structure */
  304     override = ByteJumpParse(data, idx, otn);
  305     if (override != NULL)
  306     {
  307         /* There is an override function */
  308         free(idx);
  309         override->func(sc, override->keyword, override->option, data, otn, protocol);
  310         return;
  311     }
  312 
  313     fpl = AddOptFuncToList(ByteJump, otn);
  314     fpl->type = RULE_OPTION_TYPE_BYTE_JUMP;
  315 
  316     if (add_detection_option(sc, RULE_OPTION_TYPE_BYTE_JUMP, (void *)idx, &idx_dup) == DETECTION_OPTION_EQUAL)
  317     {
  318 #ifdef DEBUG_RULE_OPTION_TREE
  319 
  320         LogMessage("Duplicate ByteJump:\n%d %d %c %c %c %c %c %c %d %d 0x%x %d %c %c\n"
  321             "%d %d %c %c %c %c %c %c %d %d 0x%x %d %c %c\n\n",
  322             idx->bytes_to_grab,
  323             idx->offset,
  324             idx->relative_flag,
  325             idx->data_string_convert_flag,
  326             idx->from_beginning_flag,
  327             idx->from_end_flag,
  328             idx->align_flag,
  329             idx->endianess,
  330             idx->base, idx->multiplier,
  331             idx->bitmask_val,
  332             idx->post_offset,
  333             idx->offset_var,
  334             idx->postoffset_var,
  335             ((ByteJumpData *)idx_dup)->bytes_to_grab,
  336             ((ByteJumpData *)idx_dup)->offset,
  337             ((ByteJumpData *)idx_dup)->relative_flag,
  338             ((ByteJumpData *)idx_dup)->data_string_convert_flag,
  339             ((ByteJumpData *)idx_dup)->from_beginning_flag,
  340             ((ByteJumpData *)idx_dup)->from_end_flag,
  341             ((ByteJumpData *)idx_dup)->align_flag,
  342             ((ByteJumpData *)idx_dup)->endianess,
  343             ((ByteJumpData *)idx_dup)->base,
  344             ((ByteJumpData *)idx_dup)->multiplier,
  345             ((ByteJumpData *)idx_dup)->bitmask_val,
  346             ((ByteJumpData *)idx_dup)->post_offset;
  347             ((ByteJumpData *)idx_dup)->offset_var;
  348             ((ByteJumpData *)idx_dup)->postoffset_var);
  349 #endif
  350         free(idx);
  351         idx = idx_dup;
  352     }
  353 
  354 
  355     /* attach it to the context node so that we can call each instance
  356      * individually
  357      */
  358     fpl->context = (void *) idx;
  359 
  360     if (idx->relative_flag == 1)
  361         fpl->isRelative = 1;
  362 }
  363 
  364 /****************************************************************************
  365  *
  366  * Function: ByteJumpParse(char *, ByteJumpData *, OptTreeNode *)
  367  *
  368  * Purpose: This is the function that is used to process the option keyword's
  369  *          arguments and attach them to the rule's data structures.
  370  *
  371  * Arguments: data => argument data
  372  *            idx => pointer to the processed argument storage
  373  *            otn => pointer to the current rule's OTN
  374  *
  375  * Returns: void function
  376  *
  377  ****************************************************************************/
  378 static ByteJumpOverrideData * ByteJumpParse(char *data, ByteJumpData *idx, OptTreeNode *otn)
  379 {
  380     char **toks;
  381     char *endp;
  382     int num_toks;
  383     char *cptr;
  384     int i =0;
  385     RuleOptByteOrderFunc tmp_byte_order_func = NULL;
  386 
  387     toks = mSplit(data, ",", 14, &num_toks, 0);
  388 
  389     if(num_toks < 2)
  390         ParseError("Bad arguments to byte_jump: %s\n", data);
  391 
  392     /* set how many bytes to process from the packet */
  393     idx->bytes_to_grab = strtoul(toks[0], &endp, 10);
  394 
  395     if(endp==toks[0])
  396     {
  397         ParseError("Unable to parse as byte value %s\n",toks[0]);
  398     }
  399 
  400     if(*endp != '\0')
  401     {
  402         ParseError("byte_jump option has bad input: %s.", toks[0]);
  403     }
  404     if(idx->bytes_to_grab > PARSELEN )
  405     {
  406         ParseError("byte_jump can't process more than "
  407                 "%d bytes!\n",PARSELEN);
  408     }
  409 
  410     /* set offset */
  411     if (isdigit(toks[1][0]) || toks[1][0] == '-')
  412     {
  413         idx->offset = strtol(toks[1], &endp, 10);
  414         idx->offset_var = -1;
  415 
  416         if(endp==toks[1])
  417         {
  418             ParseError("Unable to parse as offset %s\n",toks[1]);
  419         }
  420 
  421         if(*endp != '\0')
  422         {
  423             ParseError("byte_jump option has bad offset: %s.", toks[1]);
  424         }
  425     }
  426     else
  427     {
  428         idx->offset_var = find_value(toks[1]);
  429         if (idx->offset_var == BYTE_EXTRACT_NO_VAR)
  430         {
  431             ParseError(BYTE_JUMP_INVALID_ERR_FMT, "byte_jump : offset", toks[1]);
  432         }
  433     }
  434 
  435     idx->postoffset_var = -1;
  436     i = 2;
  437 
  438     /* is it a relative offset? */
  439     if(num_toks > 2)
  440     {
  441         while(i < num_toks)
  442         {
  443             cptr = toks[i];
  444 
  445             while(isspace((int)*cptr)) {cptr++;}
  446 
  447             if(!strcasecmp(cptr, "relative"))
  448             {
  449                 /* the offset is relative to the last pattern match */
  450                 idx->relative_flag = 1;
  451             }
  452             else if(!strcasecmp(cptr, "from_beginning"))
  453             {
  454                 idx->from_beginning_flag = 1;
  455             }
  456             else if(!strcasecmp(cptr, "from_end"))
  457             {
  458                 idx->from_end_flag = 1;
  459             }
  460             else if(!strcasecmp(cptr, "string"))
  461             {
  462                 /* the data will be represented as a string that needs
  463                  * to be converted to an int, binary is assumed otherwise
  464                  */
  465                 idx->data_string_convert_flag = 1;
  466             }
  467             else if(!strcasecmp(cptr, "little"))
  468             {
  469                 idx->endianess = LITTLE;
  470             }
  471             else if(!strcasecmp(cptr, "big"))
  472             {
  473                 /* this is the default */
  474                 idx->endianess = BIG;
  475             }
  476             else if(!strcasecmp(cptr, "hex"))
  477             {
  478                 idx->base = 16;
  479             }
  480             else if(!strcasecmp(cptr, "dec"))
  481             {
  482                 idx->base = 10;
  483             }
  484             else if(!strcasecmp(cptr, "oct"))
  485             {
  486                 idx->base = 8;
  487             }
  488             else if(!strcasecmp(cptr, "align"))
  489             {
  490                 idx->align_flag = 1;
  491             }
  492             else if(!strncasecmp(cptr, "multiplier ", 11))
  493             {
  494                 /* Format of this option is multiplier xx.
  495                  * xx is a positive base 10 number.
  496                  */
  497                 char *mval = &cptr[11];
  498                 long factor = 0;
  499                 int multiplier_len = strlen(cptr);
  500                 if (multiplier_len > 11)
  501                 {
  502                     factor = strtol(mval, &endp, 10);
  503                 }
  504                 if ((factor <= 0) || (endp != cptr + multiplier_len))
  505                 {
  506                     ParseError("invalid length multiplier \"%s\"\n",cptr);
  507                 }
  508                 idx->multiplier = factor;
  509             }
  510             else if(!strncasecmp(cptr, "post_offset ", 12))
  511             {
  512                 /* Format of this option is post_offset xx.
  513                  * xx is a positive or negative base 10 integer.
  514                  */
  515                 if (!idx->post_offset)
  516                 {
  517                   char *mval = &cptr[12];
  518                   int32_t factor = 0;
  519                   int postoffset_len = strlen(cptr);
  520                   while(isspace((int)*mval)) {mval++;}
  521                   if (postoffset_len > 12 && (isdigit(*mval) || *mval == '-' ))
  522                   {
  523                       factor = strtol(mval, &endp, 10);
  524                       idx->postoffset_var=-1;
  525                       if (endp != cptr + postoffset_len)
  526                       {
  527                           ParseError("invalid post_offset \"%s\"\n",cptr);
  528                       }
  529                       idx->post_offset = factor;
  530                   }
  531                   else
  532                   {
  533                       idx->postoffset_var = find_value(mval);
  534                       if ( idx->postoffset_var == BYTE_EXTRACT_NO_VAR)
  535                       {
  536                           ParseError(BYTE_JUMP_INVALID_ERR_FMT, "byte_jump : post_offset", mval);
  537                       }
  538                   }
  539                }
  540                else
  541                {
  542                    ParseError("byte_jump option post_offset is already configured in rule once\n");
  543                }
  544             }
  545             else if ((tmp_byte_order_func = GetByteOrderFunc(cptr)) != NULL)
  546             {
  547                 idx->byte_order_func = tmp_byte_order_func;
  548             }
  549             else if(strncasecmp(cptr,"bitmask ",8) == 0)
  550             {
  551                RuleOptionBitmaskParse(&(idx->bitmask_val) , cptr, idx->bytes_to_grab,"BYTE_JUMP");
  552             }
  553             else
  554             {
  555                 ByteJumpOverrideData *override = byteJumpOverrideFuncs;
  556 
  557                 while (override != NULL)
  558                 {
  559                     if (strcasecmp(cptr, override->option) == 0)
  560                     {
  561                         mSplitFree(&toks, num_toks);
  562                         return override;
  563                     }
  564 
  565                     override = override->next;
  566                 }
  567 
  568                 ParseError("unknown modifier \"%s\"\n",cptr);
  569             }
  570 
  571             i++;
  572         }
  573     }
  574 
  575     if (idx->bytes_to_grab > MAX_BYTES_TO_GRAB && !idx->data_string_convert_flag)
  576     {
  577         ParseError("byte_jump rule option cannot extract more than %d bytes without valid string prefix.",
  578                      MAX_BYTES_TO_GRAB);
  579     }
  580     /* idx->base is only set if the parameter is specified */
  581     if(!idx->data_string_convert_flag && idx->base)
  582     {
  583         ParseError("hex, dec and oct modifiers must be used in conjunction \n"
  584                    "        with the 'string' modifier\n");
  585     }
  586     if (idx->from_beginning_flag  && idx->from_end_flag)
  587     {
  588        ParseError("from_beginning and from_end options together in a rule is invalid config!\n");
  589     }
  590     if (idx->offset < MIN_BYTE_EXTRACT_OFFSET || idx->offset > MAX_BYTE_EXTRACT_OFFSET)
  591     {
  592         ParseError("byte_jump rule option has invalid offset. "
  593               "Valid offsets are between %d and %d.",
  594                MIN_BYTE_EXTRACT_OFFSET, MAX_BYTE_EXTRACT_OFFSET);
  595     }
  596     mSplitFree(&toks, num_toks);
  597     return NULL;
  598 }
  599 
  600 
  601 /****************************************************************************
  602  *
  603  * Function: ByteJump(char *, OptTreeNode *, OptFpList *)
  604  *
  605  * Purpose: Use this function to perform the particular detection routine
  606  *          that this rule keyword is supposed to encompass.
  607  *
  608  * Arguments: p => pointer to the decoded packet
  609  *            otn => pointer to the current rule's OTN
  610  *            fp_list => pointer to the function pointer list
  611  *
  612  * Returns: If the detection test fails, this function *must* return a zero!
  613  *          On success, it calls the next function in the detection list
  614  *
  615  ****************************************************************************/
  616 int ByteJump(void *option_data, Packet *p)
  617 {
  618     ByteJumpData *bjd = (ByteJumpData *)option_data;
  619     int rval = DETECTION_OPTION_NO_MATCH;
  620     uint32_t value = 0;
  621     uint32_t jump_value = 0;
  622     uint32_t payload_bytes_grabbed = 0;
  623     uint32_t extract_offset,extract_postoffset;
  624     int32_t offset, tmp = 0;
  625     int dsize;
  626     const uint8_t *base_ptr, *end_ptr, *start_ptr;
  627     uint8_t rst_doe_flags = 1;
  628     int search_start = 0;
  629     PROFILE_VARS;
  630 
  631     PREPROC_PROFILE_START(byteJumpPerfStats);
  632 
  633     if (Is_DetectFlag(FLAG_ALT_DETECT))
  634     {
  635         dsize = DetectBuffer.len;
  636         start_ptr = DetectBuffer.data;
  637         DEBUG_WRAP(DebugMessage(DEBUG_PATTERN_MATCH,
  638                     "Using Alternative Detect buffer!\n"););
  639     }
  640     else if(Is_DetectFlag(FLAG_ALT_DECODE))
  641     {
  642         dsize = DecodeBuffer.len;
  643         start_ptr = DecodeBuffer.data;
  644         DEBUG_WRAP(DebugMessage(DEBUG_PATTERN_MATCH,
  645                     "Using Alternative Decode buffer!\n"););
  646     }
  647     else
  648     {
  649         start_ptr = p->data;
  650         if(IsLimitedDetect(p))
  651             dsize = p->alt_dsize;
  652         else
  653             dsize = p->dsize;
  654     }
  655 
  656     /* save off whatever our ending pointer is */
  657     end_ptr = start_ptr + dsize;
  658     base_ptr = start_ptr;
  659 
  660     DEBUG_WRAP(
  661             DebugMessage(DEBUG_PATTERN_MATCH,"[*] byte jump firing...\n");
  662             DebugMessage(DEBUG_PATTERN_MATCH,"payload starts at %p\n", start_ptr);
  663             DebugMessage(DEBUG_PATTERN_MATCH,"payload ends   at %p\n", end_ptr);
  664             DebugMessage(DEBUG_PATTERN_MATCH,"doe_ptr           %p\n", doe_ptr);
  665             );  /* END DEBUG_WRAP */
  666     /* Get values from byte_extract variables, if present. */
  667     if (bjd->offset_var >= 0 )
  668     {
  669          if(bjd->offset_var == BYTE_MATH_VAR_INDEX )
  670          {
  671               bjd->offset = (int32_t) bytemath_variable;
  672          }
  673 
  674          else if(bjd->offset_var ==  COMMON_VAR_INDEX )
  675          {
  676               bjd->offset = (int32_t) common_var;
  677          }
  678          else if ( bjd->offset_var < NUM_BYTE_EXTRACT_VARS)
  679          {
  680               GetByteExtractValue(&extract_offset, bjd->offset_var);
  681               bjd->offset = (int32_t) extract_offset;
  682          }
  683     }
  684 
  685     if(bjd->relative_flag && doe_ptr)
  686     {
  687         DEBUG_WRAP(DebugMessage(DEBUG_PATTERN_MATCH,
  688                                 "Checking relative offset!\n"););
  689 
  690         /* @todo: possibly degrade to use the other buffer, seems non-intuitive
  691          *  Because doe_ptr can be "end" in the last match,
  692          *  use end + 1 for upper bound
  693          *  Bound checked also after offset is applied
  694          *  (see byte_extract() and string_extract())
  695          */
  696         if(!inBounds(start_ptr, end_ptr + 1, doe_ptr))
  697         {
  698             DEBUG_WRAP(DebugMessage(DEBUG_PATTERN_MATCH,
  699                                     "[*] byte jump bounds check failed..\n"););
  700 
  701             PREPROC_PROFILE_END(byteJumpPerfStats);
  702             return rval;
  703         }
  704 
  705         search_start = (doe_ptr - start_ptr) + bjd->offset;
  706         base_ptr = doe_ptr;
  707         rst_doe_flags = 0;
  708     }
  709     else
  710     {
  711         DEBUG_WRAP(DebugMessage(DEBUG_PATTERN_MATCH,
  712                                 "checking absolute offset %d\n", bjd->offset););
  713         search_start = bjd->offset;
  714         base_ptr = start_ptr;
  715     }
  716 
  717     if (search_start < 0)
  718     {
  719         DEBUG_WRAP(DebugMessage(DEBUG_PATTERN_MATCH,
  720                                 "[*] byte jump bounds check failed..\n"););
  721 
  722         PREPROC_PROFILE_END(byteJumpPerfStats);
  723         return rval;
  724     }
  725 
  726     base_ptr = base_ptr + bjd->offset;
  727     /* Use byte_order_func to determine endianess, if present */
  728     if (bjd->byte_order_func)
  729     {
  730         offset = (int32_t) (base_ptr - p->data);
  731         bjd->endianess = bjd->byte_order_func(p, offset);
  732         if (bjd->endianess == -1)
  733         {
  734             PREPROC_PROFILE_END(byteJumpPerfStats);
  735             return DETECTION_OPTION_NO_MATCH;
  736         }
  737     }
  738 
  739     /* Both of the extraction functions contain checks to insure the data
  740      * is always inbounds */
  741 
  742     if(!bjd->data_string_convert_flag && bjd->bytes_to_grab)
  743     {
  744         if(byte_extract(bjd->endianess, bjd->bytes_to_grab,
  745                         base_ptr, start_ptr, end_ptr, &value))
  746         {
  747             DEBUG_WRAP(DebugMessage(DEBUG_PATTERN_MATCH,
  748                                     "Byte Extraction Failed\n"););
  749             PREPROC_PROFILE_END(byteJumpPerfStats);
  750             return rval;
  751         }
  752 
  753         payload_bytes_grabbed = bjd->bytes_to_grab;
  754     }
  755     else if (bjd->data_string_convert_flag)
  756     {
  757         payload_bytes_grabbed = tmp = string_extract(bjd->bytes_to_grab, bjd->base,
  758                                                base_ptr, start_ptr, end_ptr, &value);
  759         if (tmp < 0 && bjd->bytes_to_grab)
  760         {
  761             DEBUG_WRAP(DebugMessage(DEBUG_PATTERN_MATCH,
  762                                     "Byte Extraction Failed\n"););
  763 
  764             PREPROC_PROFILE_END(byteJumpPerfStats);
  765             return rval;
  766         }
  767 
  768     }
  769 
  770     DEBUG_WRAP(DebugMessage(DEBUG_PATTERN_MATCH,
  771                             "grabbed %d of %d bytes, value = %08X\n",
  772                             payload_bytes_grabbed, bjd->bytes_to_grab, value););
  773 
  774 
  775     if(bjd->bitmask_val != 0 )
  776     {
  777         int num_tailing_zeros_bitmask = getNumberTailingZerosInBitmask(bjd->bitmask_val);
  778         value = value & bjd->bitmask_val ;
  779         if (value && num_tailing_zeros_bitmask )
  780         {
  781             value = value >> num_tailing_zeros_bitmask;
  782         }
  783     }
  784 
  785     DEBUG_WRAP(DebugMessage(DEBUG_PATTERN_MATCH,"post_bitmask operation the extracted value : 0x%08X(%u)\n", value,value););
  786     /* Adjust the jump_value (# bytes to jump forward) with the multiplier. */
  787     if (bjd->multiplier)
  788         jump_value = value * bjd->multiplier;
  789     else
  790         jump_value = value;
  791 
  792     DEBUG_WRAP(DebugMessage(DEBUG_PATTERN_MATCH,
  793                             "grabbed %d of %d bytes, after multiplier value = %08X\n",
  794                             payload_bytes_grabbed, bjd->bytes_to_grab, jump_value););
  795 
  796 
  797     /* if we need to align on 32-bit boundries, round up to the next
  798      * 32-bit value
  799      */
  800     if(bjd->align_flag)
  801     {
  802         DEBUG_WRAP(DebugMessage(DEBUG_PATTERN_MATCH,
  803                     "offset currently at %d\n", jump_value););
  804         if ((jump_value % 4) != 0)
  805         {
  806             jump_value += (4 - (jump_value % 4));
  807         }
  808         DEBUG_WRAP(DebugMessage(DEBUG_PATTERN_MATCH,
  809                     "offset aligned to %d\n", jump_value););
  810     }
  811 
  812     DEBUG_WRAP(DebugMessage(DEBUG_PATTERN_MATCH,
  813                             "Grabbed %d bytes at offset %d, value = 0x%08X\n",
  814                             payload_bytes_grabbed, bjd->offset, jump_value););
  815 
  816     if(bjd->from_beginning_flag)
  817     {
  818         /* Reset base_ptr if from_beginning */
  819         DEBUG_WRAP(DebugMessage(DEBUG_PATTERN_MATCH,
  820                                 "jumping from beginning 0x%08X(%u) bytes\n", jump_value,jump_value););
  821         base_ptr = start_ptr;
  822 
  823         /* from base, push doe_ptr ahead "value" number of bytes */
  824         SetDoePtr((base_ptr + jump_value), DOE_BUF_STD);
  825 
  826     }
  827     else if(bjd->from_end_flag)
  828     {
  829         /* Reset base_ptr if from_end */
  830         DEBUG_WRAP(DebugMessage(DEBUG_PATTERN_MATCH,
  831                                 "jumping from end 0x%08X(%u) bytes\n", jump_value,jump_value););
  832         base_ptr = end_ptr;
  833         /* from base, push doe_ptr ahead "value" number of bytes */
  834         SetDoePtr((base_ptr + jump_value), DOE_BUF_STD);
  835 
  836     }
  837     else
  838     {
  839         UpdateDoePtr((base_ptr + payload_bytes_grabbed + jump_value), rst_doe_flags);
  840     }
  841     DEBUG_WRAP(DebugMessage(DEBUG_PATTERN_MATCH,"updated doe_ptr %p\n", doe_ptr););
  842     /* Get values from byte_extract/math variables, if present. */
  843     if (bjd->postoffset_var >=0)
  844     {
  845         if(bjd->postoffset_var == BYTE_MATH_VAR_INDEX)
  846         {
  847              bjd->post_offset = (int32_t) bytemath_variable;
  848         }
  849 
  850         else if(bjd->postoffset_var == COMMON_VAR_INDEX)
  851         {
  852              bjd->post_offset = (int32_t) common_var;
  853         }
  854         else if (bjd->postoffset_var < NUM_BYTE_EXTRACT_VARS)
  855         {
  856              GetByteExtractValue(&extract_postoffset, bjd->postoffset_var);
  857              bjd->post_offset = (int32_t) extract_postoffset;
  858         }
  859     }
  860     /* now adjust using post_offset -- before bounds checking */
  861     doe_ptr += bjd->post_offset;
  862     DEBUG_WRAP(DebugMessage(DEBUG_PATTERN_MATCH,"after applying post_offset to doe_ptr %p\n", doe_ptr););
  863     if(!inBounds(start_ptr, end_ptr+1, doe_ptr))
  864     {
  865         DEBUG_WRAP(DebugMessage(DEBUG_PATTERN_MATCH,
  866                                 "doe_ptr is not in bounds %p\n", doe_ptr););
  867         PREPROC_PROFILE_END(byteJumpPerfStats);
  868         return rval;
  869     }
  870     else
  871     {
  872         rval = DETECTION_OPTION_MATCH;
  873     }
  874 
  875     PREPROC_PROFILE_END(byteJumpPerfStats);
  876     return rval;
  877 }
  878 
  879 static void ByteJumpOverrideCleanup(int signal, void *data)
  880 {
  881     if (byteJumpOverrideFuncs != NULL)
  882         ByteJumpOverrideFuncsFree();
  883 }
  884