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 <sys/types.h> 00026 #include <stdlib.h> 00027 #include <ctype.h> 00028 #include <string.h> 00029 00030 #ifdef HAVE_STRINGS_H 00031 #include <strings.h> 00032 #endif 00033 00034 #include "rules.h" 00035 #include "decode.h" 00036 #include "plugbase.h" 00037 #include "parser.h" 00038 #include "debug.h" 00039 #include "plugin_enum.h" 00040 #include "util.h" 00041 00042 typedef struct _IpTosData 00043 { 00044 u_int8_t ip_tos; 00045 u_int8_t not_flag; 00046 00047 } IpTosData; 00048 00049 void IpTosCheckInit(char *, OptTreeNode *, int); 00050 void ParseIpTos(char *, OptTreeNode *); 00051 int IpTosCheckEq(Packet *, struct _OptTreeNode *, OptFpList *); 00052 00053 00054 00055 /**************************************************************************** 00056 * 00057 * Function: SetupIpTosCheck() 00058 * 00059 * Purpose: Associate the tos keyword with IpTosCheckInit 00060 * 00061 * Arguments: None. 00062 * 00063 * Returns: void function 00064 * 00065 ****************************************************************************/ 00066 void SetupIpTosCheck(void) 00067 { 00068 /* map the keyword to an initialization/processing function */ 00069 RegisterPlugin("tos", IpTosCheckInit); 00070 DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN, "Plugin: IpTosCheck Initialized\n");); 00071 } 00072 00073 00074 /**************************************************************************** 00075 * 00076 * Function: IpTosCheckInit(char *, OptTreeNode *) 00077 * 00078 * Purpose: Setup the tos data struct and link the function into option 00079 * function pointer list 00080 * 00081 * Arguments: data => rule arguments/data 00082 * otn => pointer to the current rule option list node 00083 * 00084 * Returns: void function 00085 * 00086 ****************************************************************************/ 00087 void IpTosCheckInit(char *data, OptTreeNode *otn, int protocol) 00088 { 00089 /* multiple declaration check */ 00090 if(otn->ds_list[PLUGIN_IP_TOS_CHECK]) 00091 { 00092 FatalError("%s(%d): Multiple IP tos options in rule\n", file_name, 00093 file_line); 00094 } 00095 00096 /* allocate the data structure and attach it to the 00097 rule's data struct list */ 00098 otn->ds_list[PLUGIN_IP_TOS_CHECK] = (IpTosData *) 00099 SnortAlloc(sizeof(IpTosData)); 00100 00101 /* this is where the keyword arguments are processed and placed into the 00102 rule option's data structure */ 00103 ParseIpTos(data, otn); 00104 00105 /* finally, attach the option's detection function to the rule's 00106 detect function pointer list */ 00107 AddOptFuncToList(IpTosCheckEq, otn); 00108 } 00109 00110 00111 00112 /**************************************************************************** 00113 * 00114 * Function: ParseIpTos(char *, OptTreeNode *) 00115 * 00116 * Purpose: Convert the tos option argument to data and plug it into the 00117 * data structure 00118 * 00119 * Arguments: data => argument data 00120 * otn => pointer to the current rule's OTN 00121 * 00122 * Returns: void function 00123 * 00124 ****************************************************************************/ 00125 void ParseIpTos(char *data, OptTreeNode *otn) 00126 { 00127 IpTosData *ds_ptr; /* data struct pointer */ 00128 00129 /* set the ds pointer to make it easier to reference the option's 00130 particular data struct */ 00131 ds_ptr = otn->ds_list[PLUGIN_IP_TOS_CHECK]; 00132 00133 /* get rid of any whitespace */ 00134 while(isspace((int)*data)) 00135 { 00136 data++; 00137 } 00138 00139 if(data[0] == '!') 00140 { 00141 ds_ptr->not_flag = 1; 00142 } 00143 00144 if(index(data, (int) 'x') == NULL && index(data, (int)'X') == NULL) 00145 { 00146 ds_ptr->ip_tos = atoi(data); 00147 } 00148 else 00149 { 00150 if(index(data,(int)'x')) 00151 { 00152 ds_ptr->ip_tos = (u_char) strtol((index(data, (int)'x')+1), NULL, 16); 00153 } 00154 else 00155 { 00156 ds_ptr->ip_tos = (u_char) strtol((index(data, (int)'X')+1), NULL, 16); 00157 } 00158 } 00159 00160 DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN,"TOS set to %d\n", ds_ptr->ip_tos);); 00161 } 00162 00163 00164 /**************************************************************************** 00165 * 00166 * Function: IpTosCheckEq(char *, OptTreeNode *) 00167 * 00168 * Purpose: Test the ip header's tos field to see if its value is equal to the 00169 * value in the rule. This is useful to detect things like the 00170 * "bubonic" DoS tool. 00171 * 00172 * Arguments: data => argument data 00173 * otn => pointer to the current rule's OTN 00174 * 00175 * Returns: void function 00176 * 00177 ****************************************************************************/ 00178 int IpTosCheckEq(Packet *p, struct _OptTreeNode *otn, OptFpList *fp_list) 00179 { 00180 if(!p->iph) 00181 return 0; /* if error occured while ip header 00182 * was processed, return 0 automagically. 00183 */ 00184 00185 if((((IpTosData *)otn->ds_list[PLUGIN_IP_TOS_CHECK])->ip_tos == p->iph->ip_tos) ^ (((IpTosData *)otn->ds_list[PLUGIN_IP_TOS_CHECK])->not_flag)) 00186 { 00187 /* call the next function in the function list recursively */ 00188 return fp_list->next->OptTestFunc(p, otn, fp_list->next); 00189 } 00190 else 00191 { 00192 /* you can put debug comments here or not */ 00193 DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN,"No match\n");); 00194 } 00195 00196 /* if the test isn't successful, return 0 */ 00197 return 0; 00198 }