Main Page | Modules | Class List | Directories | File List | Class Members | File Members | Related Pages

sp_icmp_code_check.c

Go to the documentation of this file.
00001 /*
00002 ** Copyright (C) 1998-2002 Martin Roesch <roesch@sourcefire.com>
00003 **
00004 ** This program is free software; you can redistribute it and/or modify
00005 ** it under the terms of the GNU General Public License as published by
00006 ** the Free Software Foundation; either version 2 of the License, or
00007 ** (at your option) any later version.
00008 **
00009 ** This program is distributed in the hope that it will be useful,
00010 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
00011 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012 ** GNU General Public License for more details.
00013 **
00014 ** You should have received a copy of the GNU General Public License
00015 ** along with this program; if not, write to the Free Software
00016 ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
00017 */
00018 
00019 /* $Id$ */
00020 
00021 #ifdef HAVE_CONFIG_H
00022 #include "config.h"
00023 #endif
00024 
00025 #include <stdlib.h>
00026 #include <string.h>
00027 #include <ctype.h>
00028 
00029 #include "rules.h"
00030 #include "decode.h"
00031 #include "plugbase.h"
00032 #include "parser.h"
00033 #include "util.h"
00034 #include "debug.h"
00035 #include "plugin_enum.h"
00036 
00037 typedef struct _IcmpCodeCheckData
00038 {
00039     /* the icmp code number */
00040     int icmp_code;
00041     int icmp_code2;
00042     u_int8_t operator;
00043 } IcmpCodeCheckData;
00044 
00045 #define ICMP_CODE_TEST_EQ 1
00046 #define ICMP_CODE_TEST_GT 2
00047 #define ICMP_CODE_TEST_LT 3
00048 #define ICMP_CODE_TEST_RG 4
00049 
00050 
00051 void IcmpCodeCheckInit(char *, OptTreeNode *, int);
00052 void ParseIcmpCode(char *, OptTreeNode *);
00053 int IcmpCodeCheck(Packet *, struct _OptTreeNode *, OptFpList *);
00054 
00055 
00056 
00057 
00058 
00059 /****************************************************************************
00060  * 
00061  * Function: SetupIcmpCodeCheck()
00062  *
00063  * Purpose: Register the icode keyword and configuration function
00064  *
00065  * Arguments: None.
00066  *
00067  * Returns: void function
00068  *
00069  ****************************************************************************/
00070 void SetupIcmpCodeCheck(void)
00071 {
00072     /* map the keyword to an initialization/processing function */
00073     RegisterPlugin("icode", IcmpCodeCheckInit);
00074     DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN, "Plugin: IcmpCodeCheck Initialized\n"););
00075 }
00076 
00077 
00078 /****************************************************************************
00079  * 
00080  * Function: IcmpCodeCheckInit(char *, OptTreeNode *)
00081  *
00082  * Purpose: Initialize the rule data structs and parse the rule argument
00083  *          data, then link in the detection function
00084  *
00085  * Arguments: data => rule arguments/data
00086  *            otn => pointer to the current rule option list node
00087  *
00088  * Returns: void function
00089  *
00090  ****************************************************************************/
00091 void IcmpCodeCheckInit(char *data, OptTreeNode *otn, int protocol)
00092 {
00093     if(protocol != IPPROTO_ICMP)
00094     {
00095         FatalError( "%s(%d): ICMP Options on non-ICMP rule\n", file_name, file_line);
00096     }
00097 
00098     /* multiple declaration check */ 
00099     if(otn->ds_list[PLUGIN_ICMP_CODE])
00100     {
00101         FatalError("%s(%d): Multiple icmp code options in rule\n", file_name,
00102                 file_line);
00103     }
00104 
00105     /* allocate the data structure and attach it to the
00106        rule's data struct list */
00107 
00108     otn->ds_list[PLUGIN_ICMP_CODE] = (IcmpCodeCheckData *)
00109             SnortAlloc(sizeof(IcmpCodeCheckData));
00110 
00111     /* this is where the keyword arguments are processed and placed into the 
00112        rule option's data structure */
00113     ParseIcmpCode(data, otn);
00114 
00115     /* finally, attach the option's detection function to the rule's 
00116        detect function pointer list */
00117     
00118     AddOptFuncToList(IcmpCodeCheck, otn);
00119 }
00120 
00121 
00122 
00123 /****************************************************************************
00124  * 
00125  * Function: ParseIcmpCode(char *, OptTreeNode *)
00126  *
00127  * Purpose: Process the icode argument and stick it in the data struct
00128  *
00129  * Arguments: data => argument data
00130  *            otn => pointer to the current rule's OTN
00131  *
00132  * Returns: void function
00133  *
00134  ****************************************************************************/
00135 void ParseIcmpCode(char *data, OptTreeNode *otn)
00136 {
00137     char *code;
00138     IcmpCodeCheckData *ds_ptr;  /* data struct pointer */
00139 
00140     /* set the ds pointer to make it easier to reference the option's
00141        particular data struct */
00142     ds_ptr = otn->ds_list[PLUGIN_ICMP_CODE];
00143 
00144     /* set a pointer to the data so to leave the original unchanged */
00145     code = data;
00146 
00147     if(!data)
00148     {
00149         FatalError("%s (%d): No ICMP Code Specified\n", file_name,
00150                 file_line);
00151     }
00152 
00153 
00154     /* get rid of whitespace before the data */
00155     while(isspace((int)*data))
00156         data++;
00157 
00158     if(data[0] == '\0')
00159     {
00160         FatalError("%s (%d): No ICMP Code Specified\n", file_name,
00161                 file_line);
00162     }
00163 
00164     /* 
00165      * If a range is specified, put the min in icmp_code, and the max in 
00166      * icmp_code2
00167      */
00168 
00169     if (isdigit((int)*data) && strchr(data, '<') && strchr(data, '>'))
00170     {
00171         ds_ptr->icmp_code  = atoi(strtok(data, " <>"));
00172         ds_ptr->icmp_code2 = atoi(strtok(NULL, " <>"));
00173         ds_ptr->operator = ICMP_CODE_TEST_RG;
00174     }
00175     /* otherwise if its greater than... */
00176     else if (*data == '>')
00177     {
00178         data++;
00179         while(isspace((int)*data)) data++;
00180 
00181         ds_ptr->icmp_code = atoi(data);
00182         ds_ptr->operator = ICMP_CODE_TEST_GT;
00183     }
00184     /* otherwise if its less than ... */
00185     else if (*data == '<')
00186     {
00187         data++;
00188         while(isspace((int)*data)) data++;
00189 
00190         ds_ptr->icmp_code = atoi(data);
00191         ds_ptr->operator = ICMP_CODE_TEST_LT;
00192     }
00193     /* otherwise check if its a digit */
00194     else if (isdigit((int)*data))
00195     {
00196         ds_ptr->icmp_code = atoi(data);
00197         ds_ptr->operator = ICMP_CODE_TEST_EQ;
00198     }
00199     /* uh oh */
00200     else  
00201     {
00202         FatalError("%s(%d): Bad ICMP code: %s\n", file_name, 
00203                    file_line, code);
00204     }
00205 
00206     return;
00207 }
00208 
00209 
00210 /****************************************************************************
00211  * 
00212  * Function: IcmpCodeCheck(Packet *p, OptTreeNode *, OptFpList *fp_list)
00213  *
00214  * Purpose: Test the packet's ICMP code field value against the option's
00215  *          ICMP code
00216  *
00217  * Arguments: data => argument data
00218  *            otn => pointer to the current rule's OTN
00219  *
00220  * Returns: void function
00221  *
00222  ****************************************************************************/
00223 int IcmpCodeCheck(Packet *p, struct _OptTreeNode *otn, OptFpList *fp_list)
00224 {
00225     IcmpCodeCheckData *ds_ptr;
00226     int success = 0;
00227 
00228     ds_ptr = otn->ds_list[PLUGIN_ICMP_CODE];
00229 
00230     /* return 0  if we don't have an icmp header */
00231     if(!p->icmph)
00232         return 0; 
00233 
00234     switch(ds_ptr->operator)
00235     {
00236         case ICMP_CODE_TEST_EQ:
00237             if (ds_ptr->icmp_code == p->icmph->code)
00238                 success = 1;
00239             break;
00240         case ICMP_CODE_TEST_GT:
00241             if (p->icmph->code > ds_ptr->icmp_code)
00242                 success = 1;
00243             break;
00244         case ICMP_CODE_TEST_LT:
00245             if (p->icmph->code < ds_ptr->icmp_code)
00246                 success = 1;
00247             break;
00248         case ICMP_CODE_TEST_RG:
00249             if (p->icmph->code > ds_ptr->icmp_code && 
00250                     p->icmph->code < ds_ptr->icmp_code2)
00251                 success = 1;
00252             break;
00253     }
00254 
00255     if (success) 
00256     {
00257         DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN, "Got icmp code match!\n"););
00258         return fp_list->next->OptTestFunc(p, otn, fp_list->next);
00259     }
00260 
00261     /* return 0 on failed test */
00262     DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN, "Failed icmp code match!\n"););
00263     return 0;
00264 }

Generated on Sun May 14 14:51:13 2006 by  doxygen 1.4.2