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

spp_portscan2.c

Go to the documentation of this file.
00001 /* $Id$ */
00002 /*
00003 ** Copyright (C) 1998,1999,2000,2001 Martin Roesch <roesch@clark.net>
00004 ** Copyright (C) 2001 Jed Haile  <jhaile@nitrodata.com>
00005 ** Copyright (C) 2002 Sourcefire, Inc
00006 **                    Chris Green <cmg@sourcefire.com>
00007 **
00008 ** This program is free software; you can redistribute it and/or modify
00009 ** it under the terms of the GNU General Public License as published by
00010 ** the Free Software Foundation; either version 2 of the License, or
00011 ** (at your option) any later version.
00012 **
00013 ** This program is distributed in the hope that it will be useful,
00014 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
00015 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016 ** GNU General Public License for more details.
00017 **
00018 ** You should have received a copy of the GNU General Public License
00019 ** along with this program; if not, write to the Free Software
00020 ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
00021 */
00022 
00023 /* state based portscan detector
00024  *  by Jed Haile <jhaile@nitrodata.com>
00025  *  version 0.0.1
00026  *  todo:  1. track timestamp, src, dst, proto, sport/icode,
00027  *              dport/itype, length
00028  */
00029 
00030 /* ChangeLog:
00031  * * Fri Nov 22 2002 Joerg Lehrke <jlehrke@noc.de>
00032  * - fixed ignorehosts
00033  * * Tue Nov 26 2002 Joerg Lehrke <jlehrke@noc.de>
00034  * - added ignoreports
00035  * * Thu Nov 28 2002 Joerg Lehrke <jlehrke@noc.de>
00036  * - added port restriction to ignorehosts
00037  * * Tue Dec  3 2002 Joerg Lehrke <jlehrke@noc.de>
00038  * - fixed precedence problems
00039  */
00040 
00041 #ifdef HAVE_CONFIG_H
00042 #include "config.h"
00043 #endif
00044 
00045 #define MODNAME "spp_portscan2"
00046 #define MAX_TARGETS 5
00047 #define MAX_PORTS 64
00048 #define MEM_CHUNK 32
00049 #define PS_T 1
00050 #define TGT_T 2
00051 
00052 #ifndef TRUE
00053 #define TRUE 0
00054 #endif
00055 #ifndef FALSE
00056 #define FALSE 1
00057 #endif
00058 
00059 #define OPT_TARGET_COUNT "targets_max"
00060 #define OPT_MAX_SCANNER "scanners_max"
00061 #define OPT_TGT_LIMIT "target_limit"
00062 #define OPT_PORT_LIMIT "port_limit"
00063 #define OPT_TIMEOUT "timeout"
00064 #define OPT_LOG "log"
00065 
00066 #define DEFAULT_MAX_SCANNER 1000
00067 #define DEFAULT_TARGET_COUNT 1000
00068 #define DEFAULT_TARGET_LIMIT 5
00069 #define DEFAULT_PORT_LIMIT   20
00070 #define DEFAULT_TIMEOUT      60
00071 
00072 
00073 
00074 
00075 #ifndef DEBUG
00076     #ifndef INLINE
00077         #define INLINE inline
00078     #endif
00079 #else
00080     #ifdef INLINE
00081         #undef INLINE
00082     #endif
00083     #define INLINE   
00084 #endif /* DEBUG */
00085 
00086 #include "spp_portscan2.h"
00087 #include "spp_conversation.h"
00088 #include "mempool.h"
00089 #include "plugbase.h"
00090 #include "mstring.h"
00091 #include "util.h"
00092 #include "log.h"
00093 #include "parser.h"
00094 #include "detect.h"
00095 #include "rules.h"
00096 #include "decode.h"
00097 #include "debug.h"
00098 #include "ubi_SplayTree.h"
00099 #include "ubi_BinTree.h"
00100 #ifndef WIN32
00101 #include <sys/socket.h>
00102 #include <netinet/in.h>
00103 #include <arpa/inet.h>
00104 #endif /* !WIN32 */
00105 #include "generators.h"
00106 #ifdef GIDS
00107 #include "spp_stickydrop.h"
00108 #endif /* GIDS */
00109 
00110 #include <assert.h>
00111 
00112 /* this represents the incoming host */
00113 typedef struct _PortScanner
00114 {
00115     ubi_trNode Node;             /* for the splay tree */
00116     MemBucket *bucket;
00117 
00118     u_int32_t scanner_ip;
00119 
00120     struct timeval initial_time;
00121     struct timeval last_time;
00122 
00123     int port_count;     /* total count of ports this scanner has hit */
00124     int target_count;  /* total count of targets this scanner has hit */
00125     
00126     ubi_trRoot targetRoot;  /* this scanner's target tree*/
00127     ubi_trRootPtr targetRootPtr; 
00128 
00129     int targetsExceeded;
00130     int portsExceeded;
00131 
00132     int bytes;     /* counts of things that happended */
00133     int packets;
00134     
00135     u_int32_t event_id;    
00136 } Portscanner;
00137 
00138 typedef struct _ScanTarget
00139 {
00140     ubi_trNode Node;
00141     Portscanner *parent;  /*pointer to the parent Portscanner node */
00142     MemBucket *bucket;
00143 
00144     
00145     u_int32_t target_ip;
00146     int port_count;   /* number of ports on this target hit by parent portscanner*/
00147 
00148     struct timeval initial_time;
00149     struct timeval last_time;
00150 
00151     char plist[65536/8];  /* an array of bytes to store port info */
00152 } ScanTarget;
00153 
00154 typedef struct _hostNode
00155 {
00156     IpAddrSet *address;
00157     u_short hsp;         /* hi src port */
00158     u_short lsp;         /* lo src port */
00159     u_int32_t flags;     /* control flags */
00160     struct _hostNode *nextNode;
00161 } HostNode;
00162 
00163 HostNode *ignoreList; /* for ignore-hosts */
00164 
00165 /* ignore-ports-from, ignore-ports-to */
00166 int num_ports_from;
00167 int num_ports_to;
00168 u_int32_t *ignorePortFrom;
00169 u_int32_t *ignorePortTo;
00170 
00171 typedef struct _Portscan2Data
00172 {
00173     ubi_trRoot Scanners;
00174 
00175     ubi_trRootPtr ScannersPtr;
00176 
00177     u_int32_t scanner_count;
00178     u_int32_t target_count;
00179     
00180     MemPool TargetPool;
00181     MemPool ScannerPool;
00182 
00183     /** Global Program Data **/
00184     FILE *logfile;
00185     char *logpath;
00186 
00187     int tgtThreshold;   /* number of distinc targets to allow */
00188     int portThreshold;  /* number of distinct ports to allow before alerting */
00189     int timeout;
00190     char isInitialized;
00191     struct timeval prune_time;
00192 } Portscan2Data;
00193 
00194 
00195 Portscan2Data ps2data;
00196 
00197 /** external globals from rules.c **/
00198 extern char *file_name;
00199 extern int file_line;
00200 extern u_int32_t event_id;
00201 
00202 #ifdef GIDS
00203 /* stickydrop */
00204 extern SDtimeout sdt;
00205 #endif /* GIDS */
00206 
00207 /** FUNCTION PROTOTYPES **/
00208 void Scan2Init(u_char *);
00209 static int targetCompareFunc(ubi_trItemPtr , ubi_trNodePtr);
00210 
00211 /* void AddTarget(ubi_trRootPtr, u_int32_t, u_int16_t, u_int32_t); */
00212 void ParseScanmungeArgs(u_char *);
00213 /* delete the nodes from a portscanner */
00214 static int PruneTargets(Portscanner *p, u_int32_t now, int tokill);
00215 static int PrunePortscanners(u_int32_t now, int tokill, Portscanner *saveme);
00216 
00217 void SLog(Packet *, int, Portscanner *);
00218 void SAlert(Packet *, int, Portscanner *);
00219 INLINE int portIsSet(char *, int);
00220 INLINE void InitPortlist(ScanTarget *target);
00221 void setPort(char *, int);
00222 void dumpPacketStats(Portscanner *);
00223 
00224 /* For ignore hosts */
00225 void InitIgnoreHosts(u_char *);
00226 IpAddrSet* IgnoreAllocAddrNode(HostNode *);
00227 void ScanParseIp(char *, HostNode *);
00228 
00229 /* For ignore ports */
00230 void InitIgnoreFrom(u_char *);
00231 void InitIgnoreTo(u_char *);
00232 void InitIgnorePorts(u_char *, u_int32_t **, int *);
00233 u_int32_t ScanParsePort(char *);
00234 
00235 int IsIgnored(Packet *);
00236 
00237 /*************************************************************/
00238 /* Parses all of scan2's args. They are as follows:          */
00239 /* int psnodes, int targetnodes, char log, int targets,      */
00240 /* int ports, int timeout                                    */
00241 /*************************************************************/
00242 void ParseScanmungeArgs(u_char *args)
00243 {
00244     int num_toks, s_toks;
00245     char **toks = NULL;
00246     char **stoks;
00247     int i;
00248     char* index;
00249     char logpath[STD_BUF], tmp[STD_BUF];
00250 
00251     /* setup the defaults */
00252     strncpy(logpath, pv.log_dir, STD_BUF);
00253     strncpy(tmp, "/scan.log", STD_BUF);
00254     strncat(logpath, tmp, STD_BUF);
00255 
00256     /* way too low of defaults */
00257     ps2data.scanner_count = DEFAULT_MAX_SCANNER;
00258     ps2data.target_count  = DEFAULT_TARGET_COUNT;
00259     ps2data.tgtThreshold  = DEFAULT_TARGET_LIMIT;
00260     ps2data.portThreshold = DEFAULT_PORT_LIMIT;
00261     ps2data.timeout       = DEFAULT_TIMEOUT;
00262 
00263     if (args)
00264     {
00265 
00266         toks = mSplit(args, ",", 11, &num_toks, 0);
00267 
00268         i=0;
00269 
00270         while (i < num_toks)
00271         {
00272             index = toks[i];
00273 
00274             while(isspace((int)*index)) index++;
00275 
00276             stoks = mSplit(index, " ", 4, &s_toks, 0);
00277 
00278             if (!stoks[1] || stoks[1][0] == '\0')
00279             {
00280                 FatalError("%s: %s(%d) => '%s' has null value. ",
00281                            MODNAME, file_name, file_line, stoks[0]);
00282             }
00283             if(!strcasecmp(stoks[0], OPT_MAX_SCANNER))
00284             {
00285                 if(isdigit((int)stoks[1][0]))
00286                 {
00287                     /* number of psnodes */
00288                     ps2data.scanner_count = atoi(stoks[1]);
00289                     i++;
00290                 }
00291                 else
00292                 {
00293                     /* lets cool it with the leeway */
00294                     FatalError("%s: %s(%d) => '%s' has invalid value '%s'. ",
00295                                MODNAME, file_name, file_line,
00296                                stoks[0], stoks[1]);
00297                 }
00298             }
00299             else if(!strcasecmp(stoks[0], OPT_TARGET_COUNT))
00300             {
00301                 if(isdigit((int)(stoks[1][0])))
00302                 {
00303                     /* number of tgtnodes */
00304                     ps2data.target_count = atoi(stoks[1]);
00305                     i++;
00306                 }
00307                 else
00308                 {
00309                     FatalError("%s: %s(%d) => '%s' has invalid value '%s'. ",
00310                                MODNAME, file_name, file_line,
00311                                stoks[0], stoks[1]);
00312                 }
00313             }
00314             else if(!strcasecmp(stoks[0], OPT_TGT_LIMIT))
00315             {
00316                 if(isdigit((int)(stoks[1][0])))
00317                 {
00318                     /* number of targets */
00319                     ps2data.tgtThreshold = atoi(stoks[1]);
00320                     i++;
00321                 }
00322                 else
00323                 {
00324                     FatalError("%s: %s(%d) => '%s' has invalid value '%s'. ",
00325                                MODNAME, file_name, file_line,
00326                                stoks[0], stoks[1]);
00327                 }
00328             }
00329             else if(!strcasecmp(stoks[0], OPT_PORT_LIMIT))
00330             {
00331                 if(isdigit((int)(stoks[1][0])))
00332                 {
00333                     /*  number of ports */
00334                     ps2data.portThreshold = atoi(stoks[1]);
00335                     i++;
00336                 }
00337                 else
00338                 {
00339                     FatalError("%s: %s(%d) => '%s' has invalid value '%s'. ",
00340                                MODNAME, file_name, file_line,
00341                                stoks[0], stoks[1]);
00342                 }
00343             }
00344             else if(!strcasecmp(stoks[0], OPT_TIMEOUT))
00345             {
00346                 if(isdigit((int)(stoks[1][0])))
00347                 {
00348                     ps2data.timeout = atoi(stoks[1]);
00349                     i++;
00350                 }
00351                 else
00352                 {
00353                     FatalError("%s: %s(%d) => '%s' has invalid value '%s'. ",
00354                                MODNAME, file_name, file_line,
00355                                stoks[0], stoks[1]);
00356                 }
00357             }
00358             else if(!strcasecmp(stoks[0], OPT_LOG))
00359             {
00360                 if(isascii((int)(stoks[1][0])))
00361                 {
00362                     if (stoks[1][0] == '/')
00363                         strncpy (logpath, stoks[1], STD_BUF);
00364                     else
00365                     {
00366                         strncpy(logpath, pv.log_dir, STD_BUF);
00367                         strncat(logpath, "/", STD_BUF);
00368                         strncat(logpath, stoks[1], STD_BUF);
00369                     }
00370                     i++;
00371                 }
00372                 else
00373                 {
00374                     FatalError("%s: %s(%d) => '%s' has invalid value '%s'. ",
00375                                MODNAME, file_name, file_line,
00376                                stoks[0], stoks[1]);
00377                 }
00378             }
00379             else
00380             {
00381                 FatalError("%s: %s(%d) => option '%s' is undefined. ",
00382                            MODNAME, file_name, file_line, stoks[0]);
00383             }
00384 
00385             mSplitFree(&stoks, s_toks);
00386         }
00387         mSplitFree(&toks, num_toks);
00388     }           
00389     LogMessage ("    %s: %s\n", OPT_LOG, logpath);
00390     LogMessage ("    %s: %d\n", OPT_MAX_SCANNER, ps2data.scanner_count);
00391     LogMessage ("    %s: %d\n", OPT_TARGET_COUNT, ps2data.target_count);
00392     LogMessage ("    %s: %d\n", OPT_TGT_LIMIT, ps2data.tgtThreshold);
00393     LogMessage ("    %s: %d\n", OPT_PORT_LIMIT, ps2data.portThreshold);
00394     LogMessage ("    %s: %d\n", OPT_TIMEOUT, ps2data.timeout);
00395 
00396 
00397     ps2data.logfile = fopen(logpath, "a+");
00398 
00399     if(ps2data.logfile == NULL)
00400     {
00401         FatalError("Can't open logfile: %s", ps2data.logpath);
00402     }
00403 }
00404 
00405 /*************************************************************/
00406 /* Called at runtime to establish the list of hosts who are  */
00407 /* to be ignored by the portscan detector                    */
00408 /*************************************************************/
00409 void InitIgnoreHosts(u_char *hosts)
00410 {
00411     char **toks;
00412     int num_toks;
00413     int num_hosts = 0;
00414     HostNode *currentHost;
00415     /*int i;*/
00416 
00417 #ifdef DEBUG
00418     char ruleIP[16], ruleNetMask[16];
00419 #endif
00420 
00421     currentHost = NULL;
00422     ignoreList = NULL;
00423         
00424     if(hosts == NULL)
00425     {
00426         ErrorMessage(MODNAME ": ERROR: %s(%d)=> No arguments to "
00427                      "portscan2-ignorehosts, ignoring.\n",
00428                      file_name, file_line);
00429         return;
00430     }
00431 
00432     toks = mSplit(hosts, " ", 127, &num_toks, '\\');
00433         
00434     for(num_hosts = 0; num_hosts < num_toks; num_hosts++)
00435     {
00436         if((currentHost = (HostNode *) calloc(1, sizeof(HostNode))) == NULL)
00437         {
00438             FatalError("[!] ERROR: Unable to allocate space for "
00439                        "portscan IgnoreHost");
00440         } 
00441         currentHost->address = NULL; /* be paranoid */
00442         currentHost->nextNode = ignoreList;
00443         ignoreList = currentHost;
00444 
00445 #ifdef DEBUG
00446         printf(MODNAME ": InitIgnoreHosts(): Adding server %s\n", 
00447                toks[num_hosts]);
00448 #endif  /* DEBUG */
00449 
00450         ScanParseIp(toks[num_hosts], currentHost);
00451     }
00452 
00453     mSplitFree(&toks, num_toks);
00454     
00455 #ifdef DEBUG
00456     currentHost = ignoreList;
00457    
00458     while(currentHost)
00459     {
00460         memset(ruleIP, '\0', 16);
00461         memset(ruleNetMask, '\0', 16);
00462 
00463         strncpy(ruleIP, 
00464                 inet_ntoa(*(struct in_addr *) & currentHost->address->ip_addr),
00465                 15);
00466         strncpy(ruleNetMask, 
00467                 inet_ntoa(*(struct in_addr *) & currentHost->address->netmask),
00468                 15);
00469 
00470         printf(MODNAME ": InitIgnoreHosts(): Added server %s/%s\n", 
00471                ruleIP, ruleNetMask);
00472         currentHost = currentHost->nextNode;
00473     }
00474 #endif  /* DEBUG */
00475 
00476 }
00477 
00478 /************************************************************/
00479 /* Helper function to set up the list of ignored hosts      */
00480 /************************************************************/
00481 IpAddrSet* IgnoreAllocAddrNode(HostNode *host)
00482 {
00483     IpAddrSet *idx;
00484 
00485     if((idx = (IpAddrSet *) calloc(1, sizeof(IpAddrSet))) == NULL)
00486       {
00487         FatalError("[!] ERROR: Unable to allocate space for "
00488                        "portscan IP addr\n");
00489       }
00490 
00491     idx->next = host->address;
00492     host->address = idx;
00493 
00494     return idx;
00495 }
00496 
00497 /*******************************************************************/
00498 /* parses the IP's in the ignore hosts list                        */
00499 /*******************************************************************/
00500 void ScanParseIp(char *addr, HostNode *host)
00501 {
00502     char **toks;
00503     int num_toks;
00504     int i, not_flag;
00505     IpAddrSet *tmp_addr;
00506     char *enbracket, *ports;
00507     char *tmp;
00508  
00509     if(addr == NULL)
00510     {
00511         ErrorMessage("ERROR %s(%d) => Undefine address in "
00512                      "portscan-ignorehosts directive, igoring.\n", file_name, 
00513                      file_line);
00514 
00515         return;
00516     }
00517 
00518     if(*addr == '!')
00519     {
00520         host->flags |= EXCEPT_SRC_IP;
00521         addr++;
00522     }
00523  
00524     if(*addr == '$')
00525     {
00526         if((tmp = VarGet(addr + 1)) == NULL)
00527         {
00528             ErrorMessage("ERROR %s (%d) => Undefined variable \"%s\", "
00529                          "ignoring\n", file_name, file_line, addr);
00530 
00531             return;
00532         }
00533     }
00534     else
00535     {
00536         tmp = addr;
00537     }
00538  
00539     ports = strrchr(tmp, (int)'@');
00540 
00541     if (*tmp == '[')
00542     {
00543         enbracket = strrchr(tmp, (int)']');
00544         if (enbracket) *enbracket = '\x0'; /* null out the en-bracket */
00545  
00546         if (ports && enbracket && (ports < enbracket))
00547         {
00548           FatalError("[!] ERROR %s(%d) => syntax error in"
00549                      "portscan2-ignorehosts \"%s\"\n",
00550                      file_name, file_line, tmp);
00551         }       
00552         toks = mSplit(tmp+1, ",", 128, &num_toks, 0);
00553  
00554         for(i = 0; i < num_toks; i++)
00555         {
00556             tmp_addr = IgnoreAllocAddrNode(host);
00557  
00558             ParseIP(toks[i], tmp_addr);
00559         }
00560 
00561         mSplitFree(&toks, num_toks);
00562     }
00563     else
00564     {
00565         if (ports) *ports = '\x0'; /* null out the at */
00566 
00567         tmp_addr = IgnoreAllocAddrNode(host);
00568 
00569         ParseIP(tmp, tmp_addr);
00570     }
00571 
00572     if (ports)
00573     {
00574       ports++;
00575       if (ParsePort(ports, &(host->hsp), &(host->lsp), "ip", &not_flag))
00576         host->flags |= ANY_SRC_PORT;
00577       if (not_flag)
00578         host->flags |= EXCEPT_SRC_PORT;
00579     } else {
00580         host->flags |= ANY_SRC_PORT;
00581     }
00582 
00583 }
00584 
00585 /*************************************************************/
00586 /* Called at runtime to establish the list of source ports   */
00587 /* which are ignored by the portscan detector                */
00588 /*************************************************************/
00589 void InitIgnoreFrom(u_char *args)
00590 {
00591   InitIgnorePorts(args, &ignorePortFrom, &num_ports_from);
00592 }
00593 
00594 /*************************************************************/
00595 /* Called at runtime to establish the list of destination    */
00596 /* ports which are ignored by the portscan detector          */
00597 /*************************************************************/
00598 void InitIgnoreTo(u_char *args)
00599 {
00600   InitIgnorePorts(args, &ignorePortTo, &num_ports_to);
00601 }
00602 
00603 /*************************************************************/
00604 /* Called at runtime to establish the lists of ports which   */
00605 /* are ignored by the portscan detector                      */
00606 /*************************************************************/
00607 void InitIgnorePorts(u_char *list, u_int32_t **ports, int *num)
00608 {
00609     int new_ports, max_ports;
00610     u_int32_t *pool;
00611     char **toks;
00612     int num_toks;
00613 
00614     *ports = NULL;
00615     *num = 0;
00616     max_ports = 0;
00617 
00618     if(list == NULL)
00619     {
00620         ErrorMessage(MODNAME ": ERROR: %s(%d)=> No arguments to "
00621                      "portscan2-ignoreports, ignoring.\n",
00622                      file_name, file_line);
00623         return;
00624     }
00625     
00626     toks = mSplit(list, " ", MAX_PORTS, &num_toks, '\\');
00627 
00628     for(;*num < num_toks; (*num)++)
00629     {
00630       if(*num >= max_ports)
00631       {
00632         new_ports = max_ports + MEM_CHUNK;
00633         if((pool = (u_int32_t *) calloc(new_ports, sizeof(u_int32_t))) == NULL)
00634         {
00635           FatalError("[!] ERROR: Unable to allocate space for "
00636                      "portscan2-ignoreports");
00637         }
00638         if (*ports != NULL)
00639         {
00640           memcpy(pool, *ports, max_ports * sizeof(u_int32_t));
00641           free(*ports);
00642         }
00643         max_ports = new_ports;
00644         *ports = pool;
00645       }
00646       (*ports)[*num] = ScanParsePort(toks[*num]);
00647 #ifdef DEBUG
00648       printf(MODNAME ": InitIgnorePorts(): Added port %u\n", 
00649              (unsigned) (*ports)[*num]);
00650 #endif  /* DEBUG */
00651     }
00652 
00653     mSplitFree(&toks, num_toks);
00654 
00655 #ifdef DEBUG
00656     printf(MODNAME ": InitIgnorePorts(): %d port(s) added\n", *num);
00657 #endif  /* DEBUG */
00658 }
00659 
00660 /*******************************************************************/
00661 /* parses the ports in the ignore ports list                       */
00662 /*******************************************************************/
00663 u_int32_t ScanParsePort(char *port)
00664 {
00665     char *tmp;
00666  
00667     if(port == NULL)
00668     {
00669       FatalError("ERROR %s(%d) => Undefined ports in "
00670                  "portscan2-ignoreports directive\n",
00671                  file_name, file_line);
00672     }
00673 
00674     if(*port == '$')
00675     {
00676       if((tmp = VarGet(port + 1)) == NULL)
00677         {
00678           FatalError("ERROR %s (%d) => Undefined variable \"%s\"\n",
00679                      file_name, file_line, port);
00680           
00681         }
00682     }
00683     else
00684     {
00685         tmp = port;
00686     }
00687 
00688     if(!isdigit((int)tmp[0]))
00689     {
00690       FatalError("ERROR %s(%d) => Bad port list to "
00691                  "portscan2-ignoreports\n", file_name, file_line);
00692     }
00693     return((u_int32_t)atol(tmp));
00694 }
00695 
00696 
00697 /************************************************************/
00698 /* checks to see if a packet is coming from an ignored host */
00699 /************************************************************/
00700 int IsIgnored(Packet *p)
00701 {
00702 #ifdef DEBUG
00703     char sourceIP[16], ruleIP[16], ruleNetMask[16];
00704 #endif
00705     HostNode *currentHost = ignoreList;
00706     int i;
00707 
00708     for(i = 0; i < num_ports_from; i++)
00709     {
00710       if (p->sp == ignorePortFrom[i])
00711       {
00712 #ifdef DEBUG
00713             memset(sourceIP, '\0', 16);
00714             strncpy(sourceIP, inet_ntoa(p->iph->ip_src), 15);
00715             printf(MODNAME ": IsIgnored(): Source port %u from %s found!\n", 
00716                    (unsigned) p->sp, sourceIP);
00717 #endif  /* DEBUG */
00718         return(1);
00719       }
00720     }
00721 
00722     for(i = 0; i < num_ports_to; i++)
00723     {
00724       if (p->dp == ignorePortTo[i])
00725       {
00726 #ifdef DEBUG
00727             memset(sourceIP, '\0', 16);
00728             strncpy(sourceIP, inet_ntoa(p->iph->ip_src), 15);
00729             printf(MODNAME ": IsIgnored(): Destination port %u "
00730                    "from %s found!\n", 
00731                    (unsigned) p->dp, sourceIP);
00732 #endif  /* DEBUG */
00733         return(1);
00734       }
00735     }                         
00736         
00737     while(currentHost)
00738     {
00739         /*
00740          * Return 1 if the source addr is in the serverlist, 0 if nothing is
00741          * found.
00742          */
00743         if(CheckAddrPort(currentHost->address, currentHost->hsp,
00744                          currentHost->lsp, p, currentHost->flags, CHECK_SRC))
00745         {
00746 #ifdef DEBUG
00747             memset(sourceIP, '\0', 16);
00748             memset(ruleIP, '\0', 16);
00749             memset(ruleNetMask, '\0', 16);
00750             strncpy(sourceIP, inet_ntoa(p->iph->ip_src), 15);
00751             strncpy(ruleIP, inet_ntoa(*(struct in_addr*)
00752                                       &(currentHost->address->ip_addr)), 14);
00753             strncpy(ruleNetMask, 
00754                     inet_ntoa(*(struct in_addr *)
00755                               &(currentHost->address->netmask)), 15);
00756 
00757             printf(MODNAME ": IsIgnored(): Server %s found in %s/%s!\n", 
00758                    sourceIP, ruleIP, ruleNetMask);
00759 #endif  /* DEBUG */
00760             return(1);
00761         }
00762 
00763         currentHost = currentHost->nextNode;
00764     }
00765 
00766     return(0);
00767 }
00768 
00769 
00770 /********************************************************/
00771 /* takes a target node and zeros out it's port list     */
00772 /********************************************************/
00773 INLINE void InitPortlist(ScanTarget *target)
00774 {
00775     int i;
00776         
00777     for(i=0; i<65536/8; i++)
00778     {
00779         target->plist[i] = 0;
00780     }
00781 }
00782 
00783 
00784 /***************************************************/
00785 /* Add a port # to the port array for the target.  */
00786 /* This is called whenever a portscanner touches   */
00787 /* a new port on a target.                         */
00788 /***************************************************/
00789 INLINE void AddTargetPort(ScanTarget *target, u_int16_t offset, Packet *p)
00790 {
00791     /* target->plist is an array of char being treated as */
00792     /* a bitfield. There 65535 bits in the char array.    */
00793     /* Through a little voodoo we can set any particular  */
00794     /* bit in that field to 1, indicating the port has    */
00795     /* been hit. offset is the port # we wish to update   */
00796     target->plist[(offset/8)] |= 1<<(offset%8); /*  voodoo */
00797     /* increment the appropriate counters */
00798     target->port_count++;
00799     target->parent->port_count++;
00800 
00801     if(target->parent->port_count > ps2data.portThreshold)
00802     {
00803         if(target->parent->portsExceeded == FALSE) /* new ps, alert! */
00804         {
00805             SLog(p, 0, target->parent);
00806             SAlert(p, 0, target->parent);
00807             target->parent->portsExceeded = TRUE;
00808             /* dumpPacketStats(target->parent); */
00809 
00810 #ifdef GIDS
00811             if((SppStickydIsRunning()) && sdt.portscan2)
00812             {
00813                 AddIpToBlockTree(p, 0, sdt.portscan2);
00814             }
00815 #endif /* GIDS */
00816 
00817         }
00818         else /*  old portscan, log the packet */
00819         {
00820             SLog(p, 0, target->parent);
00821         }
00822     }
00823 }
00824 
00825 /*********************************/
00826 /* check to see if a port is set */
00827 /*********************************/
00828 INLINE int portIsSet(char *portlist, int offset)
00829 {
00830     /* see comment in AddTargetPort regarding this */
00831     return portlist[(offset/8)] & (1<<(offset%8));
00832 }
00833 
00834 
00835 /**************************************************/
00836 /* Add a target to a portscanners target tree.    */
00837 /* Called whenever a new target is touched by     */
00838 /* a portscanner                                  */
00839 /**************************************************/
00840 void AddTarget(Portscanner *ps, Packet *p)
00841 {
00842     struct in_addr tmp;
00843     ScanTarget *target = NULL;
00844     MemBucket *mb = NULL;
00845     int pruned;
00846     
00847     /* grab a node from the target pool */
00848     mb = mempool_alloc(&ps2data.TargetPool);
00849 
00850     if(mb == NULL)
00851     {
00852         DEBUG_WRAP(DebugMessage(DEBUG_PORTSCAN2, "Outta Target Nodes :(\n"););
00853         
00854         /*
00855          * force prune of the Portscanners ( those should have some
00856          * targets associated with them to free up )
00857          */
00858 
00859         pruned = PrunePortscanners(p->pkth->ts.tv_sec, 0, ps);
00860 
00861         if(pruned <= 0)
00862         {
00863             DEBUG_WRAP(DebugMessage(DEBUG_PORTSCAN2,
00864                                     "Pruned got %d nodes --- forcing\n"););
00865             pruned = PrunePortscanners(p->pkth->ts.tv_sec, 5, ps);
00866         }
00867 
00868         mb = mempool_alloc(&ps2data.TargetPool);
00869     }
00870 
00871     if(mb == NULL)
00872     {
00873         DEBUG_WRAP(DebugMessage(DEBUG_PORTSCAN2,
00874                                 "[*] Outta Target Nodes -- stage2 returning\n"););
00875         return;
00876     }
00877 
00878     target = (ScanTarget *) mb->data;
00879     target->bucket = mb;
00880     
00881     /* target is guaranteed to be set at this point */
00882     
00883     /* fill in the target struct */
00884     target->target_ip = (u_int32_t)p->iph->ip_dst.s_addr;
00885     target->port_count = 1;
00886     target->initial_time.tv_sec = p->pkth->ts.tv_sec;
00887     target->last_time.tv_sec = p->pkth->ts.tv_sec;
00888     target->parent = ps;
00889 
00890     InitPortlist(target);  /*  zeros out the node's port list */
00891 
00892     /* insert the new target node into the tree */
00893     if(ubi_sptInsert(ps->targetRootPtr, (ubi_btNodePtr)target,
00894                      (ubi_btNodePtr)target, NULL) == ubi_trFALSE)
00895     {
00896         DEBUG_WRAP(DebugMessage(DEBUG_PORTSCAN2,
00897                                 "Insert into Targets failed\n"););
00898     }
00899 
00900     /* update the target count */
00901     target->parent->target_count++;
00902     
00903     /* update the targets port list */
00904     AddTargetPort(target, p->dp, p);
00905     
00906     /* check thresholds to see if this qualifies as a port scan */
00907     if(ps->target_count > ps2data.tgtThreshold)
00908     {
00909         if(ps->targetsExceeded == FALSE) /*  if FALSE, then new portscan */
00910         {
00911             tmp.s_addr = ps->scanner_ip;
00912 
00913             DEBUG_WRAP(DebugMessage(DEBUG_PORTSCAN2,
00914                                     "Portscanner %s # targets exceeded\n",
00915                                     inet_ntoa(tmp)););
00916             
00917             SLog(p, 0, ps); /*  log the packet */
00918             SAlert(p, 0, ps); /*  generate an alert */
00919             ps->targetsExceeded = TRUE; /*  we have now alerted */
00920             /* dumpPacketStats(ps); */
00921 
00922 #ifdef GIDS
00923             if((SppStickydIsRunning()) && sdt.portscan2)
00924             {
00925                 AddIpToBlockTree(p, 0, sdt.portscan2);
00926             }
00927 #endif /* GIDS */
00928 
00929         }
00930         else /* alert has already been generated so log the packet */
00931         {
00932             SLog(p, 0, ps);
00933         }
00934     }
00935 }
00936 
00937 /*****************************************************************/
00938 /* Adds a new portscanner to the portscan tree, builds a target  */
00939 /* tree for this portscanner.                                    */
00940 /*****************************************************************/
00941 void AddPortScanner(Packet *p)
00942 {
00943     Portscanner *ps = NULL;
00944     MemBucket *mb = NULL;
00945     /* borrow a portscanner node from the portscanner node pool */
00946     mb = mempool_alloc(&ps2data.ScannerPool);
00947 
00948     if(mb == NULL)
00949     {
00950         DEBUG_WRAP(DebugMessage(DEBUG_PORTSCAN2, "out of Scanner Nodes\n"););
00951         /* TBD -- free up one */
00952         return;
00953     }
00954 
00955     ps = (Portscanner *) mb->data;
00956     ps->bucket = mb;
00957     
00958     /* fill in the portscanner struct */
00959     ps->scanner_ip = (u_int32_t)p->iph->ip_src.s_addr;
00960     ps->last_time.tv_sec = p->pkth->ts.tv_sec;
00961     ps->initial_time.tv_sec = p->pkth->ts.tv_sec;
00962     ps->port_count = 0; /* Add target increments this */
00963     ps->target_count = 0; /* Add target increments this */
00964     ps->targetRootPtr = &ps->targetRoot;
00965     ps->portsExceeded = FALSE;
00966     ps->targetsExceeded = FALSE;
00967 
00968     DEBUG_WRAP(DebugMessage(DEBUG_PORTSCAN2,
00969                             "Assigning a scanner ip of %s\n",
00970                             inet_ntoa(p->iph->ip_src)););
00971     
00972     /* create a new target tree for this portscanner */
00973     if(ubi_trInitTree(ps->targetRootPtr, targetCompareFunc,
00974                       0) == ubi_trFALSE)
00975     {
00976         printf("init tree failed!\n");
00977     }
00978         
00979     /* Add the target to the target tree */
00980     AddTarget(ps, p);
00981 
00982     /* get the stats for the initiating packet */
00983 
00984     /* addPacketStats(ps, p);
00985 
00986        Need to figure out what I should do with this right here
00987     */
00988 
00989     /* add this scanner to the portscan tree */
00990     /* TBD -- error check */
00991     if(ubi_sptInsert(ps2data.ScannersPtr,
00992                      (ubi_btNodePtr)ps,
00993                      (ubi_btNodePtr)ps, NULL) == ubi_trFALSE)
00994     {
00995         DEBUG_WRAP(DebugMessage(DEBUG_PORTSCAN2,
00996                                 "Insert into Scanners failed\n"););
00997     }
00998 }
00999 
01000 /*********************************************************************/
01001 /* Callback function used by splay trees to sort portscanner nodes   */
01002 /*********************************************************************/
01003 static int psCompareFunc(ubi_trItemPtr ItemPtr, ubi_trNodePtr NodePtr)
01004 {
01005     Portscanner *A = (Portscanner *) NodePtr;
01006     Portscanner *B = (Portscanner *) ItemPtr;
01007 #ifdef DEBUG
01008     #define IPLEN 256
01009     char sip[IPLEN];
01010 
01011     strncpy(sip, inet_ntoa(*(struct in_addr *) &A->scanner_ip), IPLEN);
01012     DebugMessage(DEBUG_PORTSCAN2,"psCompareFunc %s %s\n",
01013                  sip,
01014                  inet_ntoa(*(struct in_addr *) &B->scanner_ip));
01015                  
01016     #undef IPLEN
01017 #endif 
01018     
01019     
01020     
01021     if(A->scanner_ip < B->scanner_ip)
01022     {
01023         return 1;
01024     }
01025     else if(A->scanner_ip > B->scanner_ip)
01026     {
01027         return -1;
01028     }
01029 
01030     return 0;
01031 }
01032 
01033 /*********************************************************************/
01034 /* Callback function used by splay trees to sort target nodes        */
01035 /*********************************************************************/
01036 static int targetCompareFunc(ubi_trItemPtr ItemPtr, ubi_trNodePtr NodePtr)
01037 {
01038     ScanTarget *A;
01039     ScanTarget *B;
01040 
01041     A = (ScanTarget *) NodePtr;
01042     B = (ScanTarget *) ItemPtr;
01043 
01044     if(A->target_ip < B->target_ip)
01045         return 1;
01046     else if(B->target_ip < A->target_ip)
01047         return -1;
01048 
01049     return 0;
01050 }
01051 
01052 
01053 
01054 /*
01055  * Generates a snort alert when a portscan is detected
01056  */
01057 void SAlert(Packet *p, int scan_type, Portscanner *ps)
01058 {
01059     Event event;
01060     char outstring[255];
01061 
01062     snprintf(outstring, 255, SCAN2_PREFIX_STR
01063              "%s: %d targets %d ports in %d seconds",
01064              inet_ntoa(*((struct in_addr *) &ps->scanner_ip)),
01065              ps->target_count,
01066              ps->port_count,
01067              (int) (p->pkth->ts.tv_sec - ps->initial_time.tv_sec));
01068 
01069 
01070     DEBUG_WRAP(DebugMessage(DEBUG_PORTSCAN2, "%s\n", outstring););
01071     SetEvent(&event, GENERATOR_SPP_SCAN2, SCAN_TYPE, 1, 0, 0, 0);
01072 
01073     CallAlertFuncs(p, outstring, NULL, &event);
01074     ps->event_id = event.event_id;
01075 }
01076 
01077 /*******************************************************************/
01078 /* Called for each packet of a portscan. Logs interesting packet   */
01079 /* data to a text file                                             */
01080 /*******************************************************************/
01081 void SLog(Packet *p, int scan_type, Portscanner *ps)
01082 {
01083     char src[STD_BUF];
01084     char dst[STD_BUF];
01085     char timestamp[TIMEBUF_SIZE];
01086     char flagString[9];
01087 
01088     strlcpy(src, inet_ntoa(p->iph->ip_src), 16);
01089     strlcpy(dst, inet_ntoa(p->iph->ip_dst), 16);
01090     ts_print((struct timeval *) &p->pkth->ts, timestamp);
01091     
01092     if(p->tcph)
01093     { 
01094         CreateTCPFlagString(p, flagString);
01095         fprintf(ps2data.logfile,"%s TCP src: %s dst: %s sport: %u dport: %u "
01096                 "tgts: %u ports: %u flags: %s event_id: %u\n", timestamp, src, 
01097                 dst, p->sp, p->dp, ps->target_count, ps->port_count, 
01098                 flagString, ps->event_id);
01099     }
01100     else if(p->udph)
01101     {
01102         fprintf(ps2data.logfile, "%s UDP src: %s dst: %s sport: %u dport: %u "
01103                 "tgts: %u ports: %u event_id: %u\n", timestamp, src, dst, 
01104                 p->sp, p->dp, ps->target_count, ps->port_count, ps->event_id);
01105     }
01106     else if(p->icmph)
01107     {
01108         fprintf(ps2data.logfile, "%s ICMP src: %s dst: %s type: %u code: %u "
01109                 "tgts: %u event_id: %u\n", timestamp, src, dst, p->icmph->type, 
01110                 p->icmph->code, ps->target_count, ps->event_id);
01111     }
01112     
01113     fflush(ps2data.logfile);
01114 }
01115 
01116 /*********************************************************************/
01117 /* This is the main dude. Called by spp_conversation each time a new */
01118 /* session is established.                                           */
01119 /*********************************************************************/
01120 void psWatch(Packet *p)
01121 {
01122     Portscanner tmp;
01123     Portscanner *returned;
01124     ScanTarget tgt;
01125     ScanTarget *rtgt;
01126 
01127 #ifdef DEBUG
01128     #define IPLEN 256
01129     char sip[IPLEN];
01130 
01131     strncpy(sip, inet_ntoa(p->iph->ip_src), IPLEN);
01132     DebugMessage(DEBUG_PORTSCAN2,"In PsWatch... %s:%d->%s:%d state: %p\n",
01133                  sip,
01134                  p->dp,
01135                  inet_ntoa(p->iph->ip_dst),
01136                  p->sp);
01137     
01138     #undef IPLEN
01139 #endif 
01140 
01141     /* check to see if this guy is on the ignored list, if so bail */
01142     if(IsIgnored(p))
01143     {
01144         DEBUG_WRAP(DebugMessage(DEBUG_PORTSCAN2,"Matched ignore list.\n"););        
01145         return;
01146     }
01147 
01148     /* search for this portscanner in the portscan tree */
01149     tmp.scanner_ip = (u_int32_t)p->iph->ip_src.s_addr;
01150     
01151     DEBUG_WRAP(DebugMessage(DEBUG_PORTSCAN2,"scanner_ip to lookfor: %s\n", inet_ntoa(p->iph->ip_src)););        
01152     returned = (Portscanner *) ubi_sptFind(ps2data.ScannersPtr, (ubi_btItemPtr)&tmp);
01153 
01154     if(returned == NULL)  /* we have a new potential scanner */
01155     {
01156         DEBUG_WRAP(DebugMessage(DEBUG_PORTSCAN2,
01157                                 "Portscanner not found. Allocating\n", returned););
01158                 
01159         AddPortScanner(p);
01160     } /* session already logged, get out */
01161     else        
01162     {
01163 
01164         DEBUG_WRAP(DebugMessage(DEBUG_PORTSCAN2,
01165                                 "Found portscanner: %p, returned->scanner_ip: %s\n",
01166                                 returned,
01167                                 inet_ntoa(*(struct in_addr *) &returned->scanner_ip)););
01168 
01169         /* Portscanner found, new session, pdate target/port */
01170         returned->last_time.tv_sec = p->pkth->ts.tv_sec;
01171 
01172         tgt.target_ip = (u_int32_t)p->iph->ip_dst.s_addr;
01173 
01174         /* check to see if target has been hit before */
01175         rtgt = (ScanTarget *) ubi_sptFind((ubi_trRootPtr)returned->targetRootPtr, 
01176                                           (ubi_btItemPtr)&tgt);
01177 
01178         if(rtgt == NULL) /* no such target in target tree, add him */
01179         {
01180             /*  AddTarget calls AddTargetPort, so no need to call here */
01181             AddTarget(returned, p);
01182             
01183             /*              if((returned->targetsExceeded == FALSE) &&  */
01184             /*                 (returned->portsExceeded == FALSE)) */
01185             /*              { */
01186             /*                  addPacketStats(returned, p); */
01187             /*              } */
01188         }
01189         else  /* target found in target tree */
01190         {
01191             /* hasn't hit this port before */
01192             if(!portIsSet(rtgt->plist, p->dp))  
01193             {
01194                 /* update the port list for the target */
01195                 AddTargetPort(rtgt, p->dp, p);
01196                 
01197                 /*                  if ((returned->targetsExceeded == FALSE) &&  */
01198                 /*                      (returned->portsExceeded == FALSE)) */
01199                 /*                  { */
01200                 /*                      addPacketStats(returned, p); */
01201                 /*                  } */
01202             }
01203 
01204             if(p->pkth->ts.tv_sec >= (returned->initial_time.tv_sec + ps2data.timeout))
01205             {
01206                 DEBUG_WRAP(DebugMessage(DEBUG_PORTSCAN2,
01207                                         "Pruning out targets %p due to timeout\n",
01208                                         returned););
01209                 
01210                 /* Prune out old sessions... we work on a sliding window ya know */
01211                 PruneTargets(returned, p->pkth->ts.tv_sec, 0);
01212                 returned->initial_time.tv_sec = p->pkth->ts.tv_sec;
01213             }
01214         }
01215     }
01216 
01217     if(p->pkth->ts.tv_sec >= (ps2data.prune_time.tv_sec + ps2data.timeout))
01218     {
01219         DEBUG_WRAP(DebugMessage(DEBUG_PORTSCAN2,
01220                                 "Pruning out scanners due to timeout\n"););
01221 
01222         /* Cull any expired sessions out */
01223         PrunePortscanners(p->pkth->ts.tv_sec, 0, NULL);
01224         ps2data.prune_time.tv_sec = p->pkth->ts.tv_sec;
01225     }
01226 
01227     DEBUG_WRAP(DebugMessage(DEBUG_PORTSCAN2,
01228                             "leaving pswatch: Scanner count: %u\n",
01229                             ubi_trCount(ps2data.ScannersPtr)););
01230 }
01231 
01232 void SetupScan2(void)
01233 {
01234     RegisterPreprocessor("portscan2", Scan2Init);
01235     RegisterPreprocessor("portscan2-ignorehosts", InitIgnoreHosts);
01236     RegisterPreprocessor("portscan2-ignoreports-from", InitIgnoreFrom);
01237     RegisterPreprocessor("portscan2-ignoreports-to", InitIgnoreTo);
01238 }
01239 
01240 /****************************************************/
01241 /* Called at runtime to set everything up           */
01242 /****************************************************/
01243 void Scan2Init(u_char *args)
01244 {
01245     struct timeval tv;
01246     struct timezone tz;
01247 
01248     LogMessage("WARNING: the portscan2 preprocessor will be deprecated in "
01249             "the next release of snort.  Please switch to using SFPortscan.\n");
01250 
01251     memset(&ps2data, 0, sizeof(Portscan2Data));
01252 
01253     if(conv_data.isInitialized != 1)
01254     {
01255         FatalError("Please activate spp_conversation before"
01256                    " trying to activate spp_portscan2\n");
01257     }   
01258 
01259     LogMessage ("Portscan2 config:\n");
01260     ParseScanmungeArgs(args);
01261     gettimeofday(&tv, &tz);
01262 
01263     ps2data.ScannersPtr = &ps2data.Scanners;
01264     
01265     /* set up the portscanner tree */ 
01266     ubi_trInitTree(ps2data.ScannersPtr, psCompareFunc, 0);
01267 
01268     /* set up the node pools */
01269     if(mempool_init(&ps2data.ScannerPool,
01270                     ps2data.scanner_count,
01271                     sizeof(Portscanner)))
01272     {
01273         FatalError("ERROR: Can't initialize mempool for Scanners\n");
01274     }
01275     
01276     if(mempool_init(&ps2data.TargetPool , ps2data.target_count,  sizeof(ScanTarget)))
01277     {
01278         FatalError("ERROR: Can't initialize mempool for Targets\n");
01279     }
01280 
01281     ps2data.isInitialized = 1;
01282     conv_data.watch_scans = 1;
01283 }
01284 
01285 static void DeleteTarget(ScanTarget *target)
01286 {
01287     mempool_free(&ps2data.TargetPool,target->bucket);
01288 }
01289 
01290 
01291 static void DeletePortscanner(Portscanner *ps)
01292 {
01293     Portscanner *oldps;
01294     
01295     /* need to do a walk and delete all the targets */
01296     DEBUG_WRAP(DebugMessage(DEBUG_PORTSCAN2, "Deleteing portscanner %p\n", ps);
01297                DebugMessage(DEBUG_PORTSCAN2,
01298                             "ps->scanner_ip: %X\n", ps->scanner_ip);
01299                DebugMessage(DEBUG_PORTSCAN2,
01300                             "ps->initial_time: %u\n", ps->initial_time.tv_sec);
01301                DebugMessage(DEBUG_PORTSCAN2,
01302                             "ps->last_time: %u\n", ps->last_time.tv_sec);
01303                DebugMessage(DEBUG_PORTSCAN2,
01304                             "ps->targetRootPtr: %p\n", ps->targetRootPtr);
01305 
01306                );
01307 
01308     (void)ubi_trKillTree(ps->targetRootPtr, DeleteTarget);
01309 
01310     
01311     oldps = (Portscanner *) ubi_sptRemove(ps2data.ScannersPtr,
01312                                           (ubi_btNodePtr) ps);
01313         
01314     mempool_free(&ps2data.ScannerPool,ps->bucket);
01315 }
01316 
01317 
01318 /* look familiar! I thought it did.  hate redebugging this junk */
01319 static int PruneTargets(Portscanner *p, u_int32_t now, int tokill)
01320 {
01321     ScanTarget *idx;
01322     u_int32_t pruned = 0;
01323 
01324     if(ubi_trCount(p->targetRootPtr) == 0)
01325     {
01326         return 0;
01327     }
01328 
01329     /* Number of things that need to be deleted */
01330     if(tokill == 0)
01331     {
01332         idx = (ScanTarget *) ubi_btFirst((ubi_btNodePtr)p->targetRootPtr);
01333 
01334         if(idx == NULL)
01335         {
01336             return 0;
01337         }
01338 
01339         do
01340         {
01341             if((idx->last_time.tv_sec + ps2data.timeout) > now)
01342             {
01343                 ScanTarget *savidx = idx;
01344 
01345                 if(ubi_trCount(p->targetRootPtr) > 1)
01346                 {
01347                     idx = (ScanTarget *) ubi_btNext((ubi_btNodePtr)idx);
01348                     DEBUG_WRAP(DebugMessage(DEBUG_CONVERSATION,
01349                                             "pruning stale target\n"););
01350 
01351                     p->port_count -= savidx->port_count;
01352                     p->target_count--;              
01353                     savidx = (ScanTarget *)ubi_sptRemove(p->targetRootPtr, (ubi_btNodePtr) savidx);
01354                     DeleteTarget(savidx);
01355                     pruned++;
01356                 }
01357                 else
01358                 {
01359                     p->port_count -= savidx->port_count;
01360                     p->target_count--;
01361                     savidx = (ScanTarget *)ubi_sptRemove(p->targetRootPtr, (ubi_btNodePtr) savidx);
01362                     DeleteTarget(savidx);
01363                     pruned++;
01364                     return pruned;
01365                 }
01366             }
01367             else
01368             {
01369                 if(idx != NULL && ubi_trCount(p->targetRootPtr))
01370                 {
01371                     idx = (ScanTarget *) ubi_btNext((ubi_btNodePtr)idx);
01372                 }
01373                 else
01374                 {
01375                     return pruned;
01376                 }
01377             }
01378         } while(idx != NULL);
01379 
01380         return pruned;
01381     }
01382     else
01383     {
01384         while(tokill-- &&  ubi_trCount(p->targetRootPtr) > 1)
01385         {
01386             idx = (ScanTarget *) ubi_btLeafNode((ubi_btNodePtr)p->targetRootPtr);
01387             p->target_count--;
01388             DeleteTarget(idx);
01389         }
01390         return 0;
01391     }
01392 
01393     return 0;
01394 }
01395 
01396 static int PrunePortscanners(u_int32_t now, int tokill, Portscanner *saveme)
01397 {
01398     Portscanner *idx;
01399     u_int32_t pruned = 0;
01400 
01401     DEBUG_WRAP(DebugMessage(DEBUG_CONVERSATION,
01402                             "Pruneport scanners called now: "
01403                             " %u tokill: %d: saveme: %p, count: %u\n",
01404                             now, tokill, saveme,
01405                             ubi_trCount(ps2data.ScannersPtr)););
01406     
01407     if(ubi_trCount(ps2data.ScannersPtr) <= 1)
01408     {
01409         DEBUG_WRAP(DebugMessage(DEBUG_CONVERSATION,
01410                                 "1 or less to prune. returning\n"););
01411         return 0;
01412     }
01413 
01414     /* Number of things that need to be deleted */
01415     if(tokill == 0)
01416     {
01417         idx = (Portscanner *) ubi_btFirst((ubi_btNodePtr)ps2data.ScannersPtr->root);
01418 
01419         if(idx == NULL)
01420         {
01421             return 0;
01422         }
01423 
01424         do
01425         {
01426             if(idx == saveme)
01427             {
01428                 idx = (Portscanner *) ubi_btNext((ubi_btNodePtr)idx);
01429                 continue;
01430             }
01431 
01432             if((idx->last_time.tv_sec+ps2data.timeout) > now)
01433             {
01434                 Portscanner *savidx = idx;
01435 
01436                 if(ubi_trCount(ps2data.ScannersPtr) > 1)
01437                 {
01438                     idx = (Portscanner *) ubi_btNext((ubi_btNodePtr)idx);
01439                     DEBUG_WRAP(DebugMessage(DEBUG_CONVERSATION,
01440                                             "pruning stale portscanner\n"););
01441                     DeletePortscanner(savidx);
01442                     pruned++;
01443                 }
01444                 else
01445                 {
01446                     DeletePortscanner(savidx);
01447                     pruned++;
01448                     return pruned;
01449                 }
01450             }
01451             else
01452             {
01453                 if(idx != NULL && ubi_trCount(ps2data.ScannersPtr))
01454                 {
01455                     idx = (Portscanner *) ubi_btNext((ubi_btNodePtr)idx);
01456                 }
01457                 else
01458                 {                    
01459                     return pruned;
01460                 }
01461             }
01462         } while(idx != NULL);
01463 
01464         return pruned;
01465     }
01466     else
01467     {
01468         while(tokill-- &&  ubi_trCount(ps2data.ScannersPtr) > 1)
01469         {
01470             idx = (Portscanner *) ubi_btLeafNode((ubi_btNodePtr)ps2data.ScannersPtr);
01471             DeletePortscanner(idx);
01472         }
01473         return 0;
01474     }
01475 
01476     return 0;
01477 }

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