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
00038
00039
00040
00041 GlobalVars Globals;
00042
00043 int CallShutdownHandlers();
00044
00045
00046
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
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
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
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
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
00279
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
00298
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
00317
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
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
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
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
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 }