engine/hlbr.c

Go to the documentation of this file.
00001 
00008 #include "hlbr.h"
00009 #include "hlbrlib.h"
00010 #include "parse_config.h"
00011 #include "parse_rules.h"
00012 #include "main_loop.h"
00013 #include "session.h"
00014 #include "../decoders/decode.h"
00015 #include "../decoders/decode_ip.h"
00016 #include "../decoders/decode_tcp.h"
00017 #include "../tests/test.h"
00018 #include "../packets/packet.h"
00019 #include "../packets/packet_cache.h"
00020 #include "../actions/action.h"
00021 #include "../routes/route.h"
00022 #include <stdio.h>
00023 #include <string.h>
00024 #include <stdlib.h>
00025 #include <unistd.h>
00026 #include <signal.h>
00027 #ifdef _LINUX_
00028 #include <getopt.h>
00029 #endif
00030 #ifdef _SOLARIS_
00031 #include <strings.h>
00032 #endif
00033 #include <sys/types.h>
00034 #include <sys/stat.h>
00035 #include <fcntl.h>
00036 
00037 //#define DEBUGPATH ;
00038 //#define DEBUG
00039 //#define DEBUGLOCKS
00040 
00041 GlobalVars Globals;
00042 
00043 int CallShutdownHandlers();
00044 
00045 /**************************************
00046 * Create a new timer
00047 ***************************************/
00048 int CreateTimer(char* Name, unsigned int Interval, int (*TimerFunc)(int TimerID, int Time, void* User), void* User){
00049         int     TimerID;
00050 
00051         if (!TimerFunc) return TIMER_NONE;
00052         if (!Name) return TIMER_NONE;
00053         if (Interval==0) return TIMER_NONE;
00054 
00055         for (TimerID=0;TimerID<MAX_TIMERS;TimerID++){
00056                 if (Globals.Timers[TimerID].InUse==FALSE) break;
00057         }
00058         
00059         if (TimerID==MAX_TIMERS) return TIMER_NONE;
00060 
00061         Globals.Timers[TimerID].InUse=TRUE;
00062         snprintf(Globals.Timers[TimerID].Name, MAX_NAME_LEN, "%s", Name);
00063         Globals.Timers[TimerID].Interval=Interval;
00064         Globals.Timers[TimerID].LastTime=0;
00065         Globals.Timers[TimerID].User=User;
00066         Globals.Timers[TimerID].TimerFunc=TimerFunc;
00067 
00068         return TimerID;
00069 }
00070 
00071 
00075 void PrintVersion()
00076 {
00077         printf("\nHogwash Light BR (HLBR) v%i.%i\n", MAJOR_VERSION, MINOR_VERSION);
00078 //      printf("by Andre Bertelli Araujo and\n   Joao Eriberto Mota Filho\n\n");
00079         printf("http://hlbr.sourceforge.net\n");
00080         printf("(based in Jason Larsen's Hogwash)\n");
00081 }
00082 
00086 void PrintUsage(char op)
00087 {
00088         DEBUGPATH;
00089 
00090         PrintVersion();
00091 
00092         switch (op) {
00093         case 0:
00094                 printf("Utilizacao / Usage:\n");
00095                 printf("------------------\n");
00096                 printf("hlbr <args>\n");
00097                 printf("  -c  <Arquivo de configuracao / Config file>\n");
00098                 printf("  -r  <Arquivo de regras / Rules file>\n");
00099                 printf("  -l  <Diretorio de log / Log directory>\n");
00100                 printf("  -L  <Opcoes de log / Log options> (-L help)\n");
00101                 printf("  -t  Analisa regras e sai / Parse rules and exit\n");
00102                 printf("  -n  Processa n pacotes e sai / Process n packets and exit\n");
00103                 printf("  -d  Executa em modo daemon / Enter Daemon Mode (Background Execution)\n");
00104                 printf("  -v  Mostra versao e sai / Print version and exit\n");
00105                 printf("------------------\n");
00106                 printf("Exemplo / Example:\n");
00107                 printf("  hlbr -c hlbr.config -r hlbr.rules &\n");
00108                 printf("------------------\n");
00109                 printf("Os arquivos de configuracao e regras estao em /etc/hlbr/.\n");
00110                 printf("The configuration files and rules are in /etc/hlbr/.\n\n\n");   
00111                 break;
00112         case 1:
00113                 printf("Opcoes para a chave -L / Options for -L flag\n");
00114                 printf("  s  Loga inicio e fim de sessao TCP / Logs start and end of a TCP session\n");
00115                 printf("  S  Loga todos os detalhes sobre uma sessao TCP (gera MUITA saida)\n     Logs all details about a TCP session (generates TOO MUCH output)\n");
00116                 printf("Ex: hlbr -L s\n");
00117                 break;
00118         }
00119 }
00120 
00121 /******************************************
00122 * Detach this process
00123 ******************************************/
00124 int hlbr_daemon(int nochdir, int noclose){
00125         int fd;
00126 
00127         printf("Entering Daemon Mode\n");
00128 #ifdef HAS_FREOPEN
00129         if (!noclose) {
00130                 freopen("/dev/null", "r", stdin);
00131                 freopen("/dev/null", "w", stdout);
00132                 freopen("/dev/null", "w", stderr);
00133         }
00134 #endif
00135         if (!nochdir)
00136                 chdir("/");
00137 
00138 #ifdef HAS_DAEMON
00139         if ((fd = daemon(1,1)) == (-1)) {
00140                 printf("Failed to enter daemon mode\n");
00141                 exit(1);
00142         }
00143 #else   /* !HAS_DAEMON */
00144         switch (fork()){
00145         case -1:
00146                 printf("fork() failed\n");
00147                 exit(1);
00148         case 0:
00149                 break;
00150         default:
00151                 exit(0);
00152         }
00153         
00154         if (setsid() == -1) exit(0);
00155         if (!noclose && (fd=open("/dev/null", O_RDWR, 0))!=-1){
00156                 dup2(fd, 0);
00157                 dup2(fd, 1);
00158                 dup2(fd, 2);
00159                 if (fd>2) close(fd);
00160         }
00161 #endif  /* HAS_DAEMON */
00162 
00163         return TRUE;
00164 }
00165 
00170 int ParseArgs(int argc, char **argv)
00171 {
00172         int     c;
00173         char*   l;
00174         
00175         DEBUGPATH;
00176 
00177 #define HOG_PARSEARGS_FLAGS "c:r:tn:l:dhvL:"
00178 
00179         while (1) {
00180 #ifndef HAS_OPT_LONG
00181                 c = getopt(argc, argv, HOG_PARSEARGS_FLAGS);
00182 #else
00183                 int option_index = 0;
00184                 static struct option long_options[] = {
00185                         {"config", 1, 0, 'c'},
00186                         {"rules", 1, 0, 'r'},
00187                         {"test", 0, 0, 't'},
00188                         {"number", 1, 0, 'n'},
00189                         {"log", 1, 0, 'l'},                                
00190                         {"daemon", 0, 0, 'd'},
00191                         {"help", 0, 0, 'h'},
00192                         {"version", 0, 0, 'v'},
00193                         {"log-options", 1, 0, 'L'},
00194                         {0, 0, 0, 0}
00195                 };
00196 
00197                 c = getopt_long (argc, argv, HOG_PARSEARGS_FLAGS,
00198                         long_options, &option_index);
00199 #endif                                          
00200                 if (c == -1) break;
00201 
00202                 switch (c) {
00203                 case 'c':
00204                         printf("Config file is %s\n",optarg);
00205 
00206                         Globals.ConfigFilename=(char*)calloc(strlen(optarg)+1,sizeof(char));
00207                         memcpy(Globals.ConfigFilename, optarg, strlen(optarg));
00208                         break;
00209                 case 'l':
00210                         Globals.LogDir=(char*)calloc(strlen(optarg)+2,sizeof(char));
00211                         memcpy(Globals.LogDir, optarg, strlen(optarg));
00212                         if (Globals.LogDir[strlen(Globals.LogDir)-1] != '/') {
00213                                 Globals.LogDir[strlen(Globals.LogDir)] = '/';
00214                         }
00215                         PRINT1("Log directory is %s\n", Globals.LogDir);
00216                         break;                  
00217                 case 'L':
00218                         if ((!optarg) || (strncmp("help", optarg, 4) == 0)) {
00219                                 PrintUsage(1);
00220                                 exit(0);
00221                         }
00222                         l = optarg;
00223                         while (*l)
00224                                 switch (*(l++)) {
00225                                 case 's':
00226                                         PRINT("Logging sessions: start and end of sessions\n");
00227                                         Globals.logSession_StartEnd = 1;
00228                                         break;
00229                                 case 'S':
00230                                         PRINT("Logging sessions: all details\n");
00231                                         Globals.logSession_All = 1;
00232                                         break;
00233                                 default:
00234                                         PrintUsage(1);
00235                                         exit(0);
00236                                 }
00237                         break;  
00238                 case 'r':
00239                         printf("Rules file is %s\n",optarg);
00240 
00241                         Globals.RulesFilename=(char*)calloc(strlen(optarg)+1,sizeof(char));
00242                         memcpy(Globals.RulesFilename, optarg, strlen(optarg));                  
00243                         break;  
00244                 case 't':
00245                         Globals.ParseOnly=TRUE;
00246                         break;
00247                 case 'n':
00248                         Globals.PacketLimit=atoi(optarg);
00249                         break;
00250                 case 'd':
00251                         hlbr_daemon(0,0);
00252                         break;
00253                 case 'h':
00254                         PrintUsage(0);
00255                         exit(0);
00256                 case 'v':
00257                         PrintVersion();
00258                         exit(0);
00259                 default:
00260                         printf("Unknown option\n");     
00261                 }       
00262         }
00263 
00264         if (!Globals.LogDir) {
00265                 Globals.LogDir = calloc(5,1);
00266         }
00267         if (Globals.logSession_StartEnd || Globals.logSession_All) {
00268                 snprintf(Globals.logSessionFile.fname, 1024, "%s%s", 
00269                          Globals.LogDir, "sessions.log");
00270                 PRINT1("Sessions log file is %s\n", Globals.logSessionFile.fname);
00271         }
00272 
00273 
00274         return TRUE;
00275 }
00276 
00277 /**************************************************
00278 * Abstract away the thread locking for 
00279 * ease of programming
00280 **************************************************/
00281 int hlbr_mutex_lock(pthread_mutex_t*    mutex, int ID, int* LockID){
00282 #ifndef HAS_THREADS
00283         return TRUE;
00284 #else
00285         int     result;
00286         
00287         if (!Globals.UseThreads) return TRUE;   
00288         result = pthread_mutex_lock(mutex);
00289 #ifdef DEBUGLOCKS       
00290         *LockID=ID;
00291 #endif  
00292         return result;
00293 #endif
00294 }
00295 
00296 /**************************************************
00297 * Abstract away the thread locking for 
00298 * ease of programming
00299 **************************************************/
00300 int hlbr_mutex_trylock(pthread_mutex_t* mutex, int ID, int* LockID){
00301 #ifndef HAS_THREADS
00302         return TRUE;
00303 #else
00304         int result;
00305         
00306         if (!Globals.UseThreads) return TRUE;
00307         result = pthread_mutex_trylock(mutex);
00308 #ifdef DEBUGLOCKS       
00309         *LockID=ID;
00310 #endif  
00311         return result;
00312 #endif
00313 }
00314 
00315 /**************************************************
00316 * Abstract away the thread locking for 
00317 * ease of programming
00318 **************************************************/
00319 int hlbr_mutex_unlock(pthread_mutex_t*  mutex){
00320 #ifndef HAS_THREADS
00321         return TRUE;
00322 #else
00323         if (!Globals.UseThreads) return TRUE;
00324         return pthread_mutex_unlock(mutex);
00325 #endif
00326 }
00327 
00331 void HandleSignal(int signal)
00332 {
00333         DEBUGPATH;
00334 
00335         switch (signal) {
00336         case SIGINT:
00337         case SIGQUIT:
00338         case SIGTERM:
00339                 printf("Signal %i recieved. Shutting down pid %i\n", signal, getpid()); 
00340                 Globals.Done=TRUE;
00341                 break;
00342         }
00343 }
00344 
00345 /*************************************
00346 * The one and only main
00347 **************************************/
00348 int main(int argc, char**argv){
00349 
00350         bzero(&Globals, sizeof(GlobalVars));
00351         Globals.IdleCount=MAX_PACKETS;
00352         Globals.PacketLimit=-1;
00353 
00354         if (argc==1) {
00355                 PrintUsage(0);
00356                 return FALSE;
00357         }       
00358         
00359         if (!ParseArgs(argc, argv)){
00360                 printf("Couldn't understand command line, quitting\n\n");
00361                 PrintUsage(0);
00362                 return FALSE;
00363         }
00364 
00365         if (!InitDecoders()) {
00366                 printf("Error initializing decoders\n");
00367                 return FALSE;
00368         }
00369 
00370         if (!InitTests()) {
00371                 printf("Error initializing tests\n");
00372                 return FALSE;
00373         }
00374 
00375         if (!InitActions()) {
00376                 printf("Error initializing actions\n");
00377                 return FALSE;
00378         }
00379 
00380         if (!InitSession()) {
00381                 printf("Error initializing session tracker\n");
00382                 return FALSE;
00383         }
00384                 
00385         if (!InitRoutes()) {
00386                 printf("Error initializing route handlers\n");
00387                 return FALSE;
00388         }
00389 
00390         if (!ParseConfig()) {
00391                 printf("Error loading config file\n");
00392                 return FALSE;
00393         }
00394 
00395         if (!ParseRules(Globals.RulesFilename)) {
00396                 printf("Error loading rules file\n");
00397                 return FALSE;
00398         }
00399         printf("Loaded %i rules\n",Globals.NumRules);
00400 
00401         if (!TestsFinishSetup()) {
00402                 printf("Tests failed finish setup\n");
00403                 return FALSE;
00404         }
00405 
00406                         
00407         if (Globals.ParseOnly) return TRUE;
00408 
00409         if (!OpenInterfaces()){
00410                 printf("Error initializing interfaces\n");
00411                 return FALSE;
00412         }
00413 
00414         /*start up the signal handlers*/
00415         signal(SIGINT, HandleSignal);
00416         signal(SIGQUIT, HandleSignal);
00417         signal(SIGTERM, HandleSignal);
00418         signal(SIGPIPE, SIG_IGN);
00419 
00420 #ifndef HAS_THREADS
00421         Globals.UseThreads=FALSE;
00422 #ifdef DEBUG
00423         printf("No Thread Suppport. Forcing Non-Threaded Mode.\n");
00424 #endif  
00425 #endif
00426 
00427         if (Globals.UseThreads)
00428                 MainLoopThreaded();
00429         else
00430                 MainLoop();
00431 
00432         printf("HLBR is all done.  Calling shutdown handlers\n");
00433         CallShutdownHandlers();
00434 
00435         return TRUE;
00436 }
00437 
00438 /**************************************
00439 * Put this somewhere else later
00440 ***************************************/
00441 int GetListByName(char* Name){
00442         int     i;
00443 
00444         DEBUGPATH;
00445 
00446         for (i=0;i<Globals.NumLists;i++){
00447                 if (strcasecmp(Globals.Lists[i].Name, Name)==0) return i;
00448         }
00449         
00450         return LIST_NONE;
00451 
00452 }
00453 
00458 int AddShutdownHandler(int (*func)(void* data), void* data)
00459 {
00460         FuncList*       f;
00461         FuncList*       this;
00462         
00463         DEBUGPATH;
00464 
00465         f = calloc(sizeof(FuncList),1);
00466         f->Func = func;
00467         f->Data = data;
00468 
00469         if (!Globals.ShutdownFuncs) {
00470                 Globals.ShutdownFuncs = f;
00471                 return TRUE;
00472         }else{
00473                 this = Globals.ShutdownFuncs;
00474                 while (this->Next) this = this->Next;
00475                 this->Next = f;
00476                 return TRUE;
00477         }
00478 }
00479 
00484 int CallShutdownHandlers()
00485 {
00486         FuncList*       this;
00487         
00488         DEBUGPATH;
00489 
00490         this = Globals.ShutdownFuncs;
00491         while (this) {
00492                 if (!this->Func(this->Data)) {
00493                         printf("Shutdown handler failed\n");
00494                 }
00495                 this = this->Next;
00496         }
00497         
00498         return TRUE;
00499 }
00500 
00501 
00502 
00507 void PrintPacketSummary(FILE* stream, int PacketSlot, IPData* IData, TCPData* TData, char newline)
00508 {
00509         if (!IData) {
00510                 if (!TData) {
00511                         if (PacketSlot != -1)
00512                                 fprintf(stream, "P:%u -%c", PacketSlot,
00513                                         (newline ? '\n' : ' '));
00514                 } else 
00515                         // No IP data but TCP data?...
00516                         fprintf(stream, "P:%u TCP ?.?.?.?:%d->?.?.?.?:%d [%u ack:%u]%c",
00517                 PacketSlot, ntohs(TData->Header->source), ntohs(TData->Header->dest),
00518                 TData->Header->seq, TData->Header->ack_seq,
00519                 (newline ? '\n' : ' '));
00520                 return;
00521         }
00522         if (!TData) {
00523                 if (PacketSlot != -1)
00524                         fprintf(stream, "P:%u IP %d.%d.%d.%d->%d.%d.%d.%d%c", PacketSlot,
00525                                 IP_BYTES(IData->Header->saddr), IP_BYTES(IData->Header->daddr),
00526                                 (newline ? '\n' : ' '));
00527                 return;
00528         }
00529         fprintf(stream, "P:%u TCP %d.%d.%d.%d:%d->%d.%d.%d.%d:%d [%u",
00530                 PacketSlot,
00531                 IP_BYTES(IData->Header->saddr), ntohs(TData->Header->source),
00532                 IP_BYTES(IData->Header->daddr), ntohs(TData->Header->dest),
00533                 TData->Header->seq);
00534         if (TData->Header->ack_seq)
00535                 fprintf(stream, " ack:%u", TData->Header->ack_seq);
00536         if (TData->Header->syn || TData->Header->fin || TData->Header->rst) {
00537                 putc(' ', stream);
00538                 if (TData->Header->syn) putc('s', stream);
00539                 if (TData->Header->fin) putc('f', stream);
00540                 if (TData->Header->rst) putc('r', stream);
00541         }
00542         putc(']', stream);
00543         if (newline)
00544                 putc('\n', stream);
00545         return;
00546 }
00547 
00554 void PrintSessionSummary(FILE* stream, PP* Port, char newline)
00555 {
00556         fprintf(stream, "S:%d, %d packets%c", Port->SessionID, Port->TCPCount,
00557                 (newline ? '\n' : ' '));
00558         
00559         return;
00560 }
00561 
00566 void PrintSessionBuffer(FILE* stream, PP* Port)
00567 {
00568         int i;
00569 
00570         fprintf(stream, "Session:%d (%d.%d.%d.%d:%d->%d.%d.%d.%d:%d)\n",
00571                 Port->SessionID, IP_BYTES(Port->Parent->IP1), Port->Port1,
00572                 IP_BYTES(Port->Parent->IP2), Port->Port2);
00573         if (Port->Stream0) {
00574                 fprintf(stream, "\tStream0:\n");
00575                 for (i=0; i < (Port->Stream0->LastSeq - Port->Stream0->TopSeq + 1); i++)
00576                         putc(
00577                                 (Port->Stream0->Payloads[i] >= 32 || Port->Stream0->Payloads[i] <=127
00578                                  ? Port->Stream0->Payloads[i] : '.'),
00579                                 stream
00580                                 );
00581                 putc(10, stream);
00582         }
00583         if (Port->Stream1) {
00584                 fprintf(stream, "\tStream1:\n");
00585                 for (i=0; i < (Port->Stream1->LastSeq - Port->Stream1->TopSeq + 1); i++)
00586                         putc(
00587                                 (Port->Stream1->Payloads[i] >= 32 || Port->Stream1->Payloads[i] <=127
00588                                  ? Port->Stream1->Payloads[i] : '.'),
00589                                 stream
00590                                 );
00591                 putc(10, stream);
00592         }
00593         
00594         return;
00595 }

Generated on Sat Jul 7 23:33:10 2007 for HLBR by  doxygen 1.5.2