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

sp_icmp_type_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 "debug.h"
00034 #include "util.h"
00035 #include "plugin_enum.h"
00036 #include "sp_icmp_type_check.h"
00037 
00038 
00039  
00040 void IcmpTypeCheckInit(char *, OptTreeNode *, int);
00041 void ParseIcmpType(char *, OptTreeNode *);
00042 int IcmpTypeCheck(Packet *, struct _OptTreeNode *, OptFpList *);
00043 
00044 
00045 
00046 /****************************************************************************
00047  * 
00048  * Function: SetupIcmpTypeCheck()
00049  *
00050  * Purpose: Register the itype keyword and configuration function
00051  *
00052  * Arguments: None.
00053  *
00054  * Returns: void function
00055  *
00056  ****************************************************************************/
00057 void SetupIcmpTypeCheck(void)
00058 {
00059     /* map the keyword to an initialization/processing function */
00060     RegisterPlugin("itype", IcmpTypeCheckInit);
00061     DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN,"Plugin: IcmpTypeCheck Initialized\n"););
00062 }
00063 
00064 
00065 /****************************************************************************
00066  * 
00067  * Function: IcmpTypeCheckInit(char *, OptTreeNode *)
00068  *
00069  * Purpose: Initialize the rule data structs and parse the rule argument
00070  *          data, then link in the detection function
00071  *
00072  * Arguments: data => rule arguments/data
00073  *            otn => pointer to the current rule option list node
00074  *
00075  * Returns: void function
00076  *
00077  ****************************************************************************/
00078 void IcmpTypeCheckInit(char *data, OptTreeNode *otn, int protocol)
00079 {
00080     if(protocol != IPPROTO_ICMP)
00081     {
00082         FatalError("%s(%d): ICMP Options on non-ICMP rule\n", file_name, file_line);
00083     }
00084     
00085     /* multiple declaration check */ 
00086     if(otn->ds_list[PLUGIN_ICMP_TYPE])
00087     {
00088         FatalError("%s(%d): Multiple ICMP type options in rule\n", file_name,
00089                 file_line);
00090     }
00091         
00092     /* allocate the data structure and attach it to the
00093        rule's data struct list */
00094     otn->ds_list[PLUGIN_ICMP_TYPE] = (IcmpTypeCheckData *)
00095             SnortAlloc(sizeof(IcmpTypeCheckData));
00096 
00097     /* this is where the keyword arguments are processed and placed into the 
00098        rule option's data structure */
00099     ParseIcmpType(data, otn);
00100 
00101     /* finally, attach the option's detection function to the rule's 
00102        detect function pointer list */
00103     AddOptFuncToList(IcmpTypeCheck, otn);
00104 }
00105 
00106 
00107 
00108 /****************************************************************************
00109  * 
00110  * Function: ParseIcmpType(char *, OptTreeNode *)
00111  *
00112  * Purpose: Process the itype argument and stick it in the data struct
00113  *
00114  * Arguments: data => argument data
00115  *            otn => pointer to the current rule's OTN
00116  *
00117  * Returns: void function
00118  *
00119  ****************************************************************************/
00120 void ParseIcmpType(char *data, OptTreeNode *otn)
00121 {
00122     char *type;
00123     IcmpTypeCheckData *ds_ptr;  /* data struct pointer */
00124 
00125     /* set the ds pointer to make it easier to reference the option's
00126        particular data struct */
00127     ds_ptr = otn->ds_list[PLUGIN_ICMP_TYPE];
00128 
00129     /* set a pointer to the data so to leave the original unchanged */
00130     type = data;
00131 
00132     if(!data)
00133     {
00134         FatalError("%s (%d): No ICMP Type Specified : %s\n", file_name, 
00135                 file_line, type);
00136     }
00137     
00138     /* get rid of spaces before the data */
00139     while(isspace((int)*data))
00140         data++;
00141 
00142     if(data[0] == '\0')
00143     {
00144         FatalError( "%s (%d): No ICMP Type Specified : %s\n", file_name,
00145                 file_line, type);
00146     }
00147 
00148     /*
00149      * if a range is specified, put the min in icmp_type, and the max in 
00150      * icmp_type2
00151      */
00152 
00153     if (isdigit((int)*data) && strchr(data, '<') && strchr(data, '>'))
00154     {
00155         ds_ptr->icmp_type  = atoi(strtok(data, " <>"));
00156         ds_ptr->icmp_type2 = atoi(strtok(NULL, " <>"));
00157         ds_ptr->operator = ICMP_TYPE_TEST_RG;
00158 
00159         /* all done */
00160         return;
00161     }
00162     /* otherwise if its greater than... */
00163     else if (*data == '>')
00164     {
00165         data++;
00166         while(isspace((int)*data)) data++;
00167 
00168         ds_ptr->icmp_type = atoi(data);
00169         ds_ptr->operator = ICMP_TYPE_TEST_GT;
00170     }
00171     /* otherwise if its less than ... */
00172     else if (*data == '<')
00173     {
00174         data++;
00175         while(isspace((int)*data)) data++;
00176 
00177         ds_ptr->icmp_type = atoi(data);
00178         ds_ptr->operator  = ICMP_TYPE_TEST_LT;
00179     }
00180     /* otherwise check if its a digit */
00181     else if (isdigit((int)*data))
00182     {
00183         ds_ptr->icmp_type = atoi(data);
00184         ds_ptr->operator = ICMP_TYPE_TEST_EQ;
00185     }
00186     /* uh oh */
00187     else 
00188     {
00189         FatalError("%s (%d): Bad ICMP type: %s\n", file_name, file_line, 
00190                 type);
00191     }
00192 
00193     return;
00194 }
00195 
00196 /****************************************************************************
00197  * 
00198  * Function: IcmpTypeCheck(char *, OptTreeNode *)
00199  *
00200  * Purpose: Test the packet's ICMP type field value against the option's
00201  *          ICMP type
00202  *
00203  * Arguments: data => argument data
00204  *            otn => pointer to the current rule's OTN
00205  *
00206  * Returns: void function
00207  *
00208  ****************************************************************************/
00209 int IcmpTypeCheck(Packet *p, struct _OptTreeNode *otn, OptFpList *fp_list)
00210 {
00211     IcmpTypeCheckData *ds_ptr;
00212     int success = 0;
00213 
00214     ds_ptr = otn->ds_list[PLUGIN_ICMP_TYPE];
00215 
00216     /* return 0  if we don't have an icmp header */
00217     if(!p->icmph)
00218         return 0;
00219 
00220     switch(ds_ptr->operator)
00221     {
00222         case ICMP_TYPE_TEST_EQ:
00223             if (p->icmph->type == ds_ptr->icmp_type)
00224                 success = 1;
00225             break;
00226         case ICMP_TYPE_TEST_GT:
00227             if (p->icmph->type > ds_ptr->icmp_type)
00228                 success = 1;
00229             break;
00230         case ICMP_TYPE_TEST_LT:
00231             if (p->icmph->type < ds_ptr->icmp_type)
00232                 success = 1;
00233             break;
00234         case ICMP_TYPE_TEST_RG:
00235             if (p->icmph->type > ds_ptr->icmp_type && 
00236                     p->icmph->type < ds_ptr->icmp_type2)
00237                 success = 1;
00238             break;
00239     }
00240 
00241     if (success)
00242     {
00243         DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN, "Got icmp type match!\n"););
00244         return fp_list->next->OptTestFunc(p, otn, fp_list->next);
00245     }
00246 
00247     /* return 0 on failed test */
00248     DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN, "Failed icmp code match!\n"););
00249     return 0;
00250 }

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