"Fossies" - the Fresh Open Source Software Archive

Member "snort-2.9.17/src/preprocessors/spp_sfportscan.c" (16 Oct 2020, 49966 Bytes) of package /linux/misc/snort-2.9.17.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "spp_sfportscan.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 2.9.16.1_vs_2.9.17.

    1 /****************************************************************************
    2  *
    3  * Copyright (C) 2014-2020 Cisco and/or its affiliates. All rights reserved.
    4  * Copyright (C) 2004-2013 Sourcefire, Inc.
    5  *
    6  * This program is free software; you can redistribute it and/or modify
    7  * it under the terms of the GNU General Public License Version 2 as
    8  * published by the Free Software Foundation.  You may not use, modify or
    9  * distribute this program under any other version of the GNU General
   10  * Public License.
   11  *
   12  * This program is distributed in the hope that it will be useful,
   13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
   14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   15  * GNU General Public License for more details.
   16  *
   17  * You should have received a copy of the GNU General Public License
   18  * along with this program; if not, write to the Free Software
   19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
   20  *
   21  ****************************************************************************/
   22 
   23 /*
   24 **  @file       spp_sfportscan.c
   25 **
   26 **  @author     Daniel Roelker <droelker@sourcefire.com>
   27 **
   28 **  @brief      Portscan detection
   29 **
   30 **  NOTES
   31 **    - User Configuration:  The following is a list of parameters that can
   32 **      be configured through the user interface:
   33 **
   34 **      proto  { tcp udp icmp ip all }
   35 **      scan_type { portscan portsweep decoy_portscan distributed_portscan all }
   36 **      sense_level { high }    # high, medium, low
   37 **      watch_ip { }            # list of IPs, CIDR blocks
   38 **      ignore_scanners { }     # list of IPs, CIDR blocks
   39 **      ignore_scanned { }      # list of IPs, CIDR blocks
   40 **      memcap { 10000000 }     # number of max bytes to allocate
   41 **      logfile { /tmp/ps.log } # file to log detailed portscan info
   42 */
   43 
   44 #include <assert.h>
   45 #include <sys/types.h>
   46 #include <errno.h>
   47 
   48 #ifndef WIN32
   49 # include <sys/socket.h>
   50 # include <netinet/in.h>
   51 # include <arpa/inet.h>
   52 #endif /* !WIN32 */
   53 
   54 #ifdef HAVE_CONFIG_H
   55 #include "config.h"
   56 #endif
   57 
   58 #include "decode.h"
   59 #include "encode.h"
   60 #include "plugbase.h"
   61 #include "generators.h"
   62 #include "event_wrapper.h"
   63 #include "util.h"
   64 #include "ipobj.h"
   65 #include "checksum.h"
   66 #include "packet_time.h"
   67 #include "snort.h"
   68 #include "sfthreshold.h"
   69 #include "sfsnprintfappend.h"
   70 #include "sf_iph.h"
   71 #include "session_api.h"
   72 #include "sfdaq.h"
   73 
   74 #include "portscan.h"
   75 
   76 #include "profiler.h"
   77 #include "reload.h"
   78 
   79 #ifdef REG_TEST
   80 #include "reg_test.h"
   81 #endif
   82 
   83 
   84 #define DELIMITERS " \t\n"
   85 #define TOKEN_ARG_BEGIN "{"
   86 #define TOKEN_ARG_END   "}"
   87 
   88 #define PROTO_BUFFER_SIZE 256
   89 
   90 extern char *file_name;
   91 extern int   file_line;
   92 
   93 tSfPolicyUserContextId portscan_config = NULL;
   94 PortscanConfig *portscan_eval_config = NULL;
   95 
   96 static Packet *g_tmp_pkt = NULL;
   97 static FILE   *g_logfile = NULL;
   98 
   99 #ifdef PERF_PROFILING
  100 PreprocStats sfpsPerfStats;
  101 #endif
  102 
  103 static void PortscanResetFunction(int signal, void *foo);
  104 static void PortscanResetStatsFunction(int signal, void *foo);
  105 static void ParsePortscan(struct _SnortConfig *, PortscanConfig *, char *);
  106 static void PortscanFreeConfigs(tSfPolicyUserContextId );
  107 static void PortscanFreeConfig(PortscanConfig *);
  108 static void PortscanOpenLogFile(struct _SnortConfig *, void *);
  109 static int PortscanGetProtoBits(int);
  110 
  111 #ifdef SNORT_RELOAD
  112 static void PortscanReload(struct _SnortConfig *, char *, void **);
  113 static int PortscanReloadVerify(struct _SnortConfig *, void *);
  114 static void * PortscanReloadSwap(struct _SnortConfig *, void *);
  115 static void PortscanReloadSwapFree(void *);
  116 #endif
  117 
  118 /*
  119 **  NAME
  120 **    PortscanPacketInit::
  121 */
  122 /**
  123 **  Initialize the Packet structure buffer so we can generate our
  124 **  alert packets for portscan.  We initialize the various fields in
  125 **  the Packet structure and set the hardware layer for easy identification
  126 **  by user interfaces.
  127 **
  128 **  @return int
  129 **
  130 **  @retval !0 initialization failed
  131 **  @retval  0 success
  132 */
  133 #define IPPROTO_PS 0xFF
  134 
  135 static int PortscanPacketInit(void)
  136 {
  137     g_tmp_pkt = Encode_New();
  138     return 0;
  139 }
  140 
  141 void PortscanCleanExitFunction(int signal, void *foo)
  142 {
  143     ps_cleanup();
  144 
  145     Encode_Delete(g_tmp_pkt);
  146     g_tmp_pkt = NULL;
  147 
  148     PortscanFreeConfigs(portscan_config);
  149     portscan_config = NULL;
  150 }
  151 
  152 
  153 static void PortscanResetFunction(int signal, void *foo)
  154 {
  155     ps_reset();
  156 }
  157 
  158 static void PortscanResetStatsFunction(int signal, void *foo)
  159 {
  160     return;
  161 }
  162 
  163 /*
  164 **  NAME
  165 **    MakeProtoInfo::
  166 */
  167 /**
  168 **  This routine makes the portscan payload for the events.  The listed
  169 **  info is:
  170 **    - priority count (number of error transmissions RST/ICMP UNREACH)
  171 **    - connection count (number of protocol connections SYN)
  172 **    - ip count (number of IPs that communicated with host)
  173 **    - ip range (low to high range of IPs)
  174 **    - port count (number of port changes that occurred on host)
  175 **    - port range (low to high range of ports connected too)
  176 **
  177 **  @return integer
  178 **
  179 **  @retval -1 buffer not large enough
  180 **  @retval  0 successful
  181 */
  182 static int MakeProtoInfo(PS_PROTO *proto, u_char *buffer, u_int *total_size)
  183 {
  184     int             dsize;
  185     sfaddr_t        *ip1, *ip2;
  186 
  187 
  188     if(!total_size || !buffer)
  189         return -1;
  190 
  191     dsize = (g_tmp_pkt->max_dsize - *total_size);
  192 
  193     if(dsize < PROTO_BUFFER_SIZE)
  194        return -1;
  195 
  196     ip1 = &proto->low_ip;
  197     ip2 = &proto->high_ip;
  198 
  199     if(proto->alerts == PS_ALERT_PORTSWEEP ||
  200        proto->alerts == PS_ALERT_PORTSWEEP_FILTERED)
  201     {
  202         SnortSnprintf((char *)buffer, PROTO_BUFFER_SIZE,
  203                       "Priority Count: %d\n"
  204                       "Connection Count: %d\n"
  205                       "IP Count: %d\n"
  206                       "Scanned IP Range: %s:",
  207                       proto->priority_count,
  208                       proto->connection_count,
  209                       proto->u_ip_count,
  210                       inet_ntoa(ip1));
  211 
  212         /* Now print the high ip into the buffer.  This saves us
  213          * from having to copy the results of inet_ntoa (which is
  214          * a static buffer) to avoid the reuse of that buffer when
  215          * more than one use of inet_ntoa is within the same printf.
  216          */
  217         SnortSnprintfAppend((char *)buffer, PROTO_BUFFER_SIZE,
  218                       "%s\n"
  219                       "Port/Proto Count: %d\n"
  220                       "Port/Proto Range: %d:%d\n",
  221                       inet_ntoa(ip2),
  222                       proto->u_port_count,
  223                       proto->low_p,
  224                       proto->high_p);
  225     }
  226     else
  227     {
  228         SnortSnprintf((char *)buffer, PROTO_BUFFER_SIZE,
  229                       "Priority Count: %d\n"
  230                       "Connection Count: %d\n"
  231                       "IP Count: %d\n"
  232                       "Scanner IP Range: %s:",
  233                       proto->priority_count,
  234                       proto->connection_count,
  235                       proto->u_ip_count,
  236                       inet_ntoa(ip1)
  237                       );
  238 
  239         /* Now print the high ip into the buffer.  This saves us
  240          * from having to copy the results of inet_ntoa (which is
  241          * a static buffer) to avoid the reuse of that buffer when
  242          * more than one use of inet_ntoa is within the same printf.
  243          */
  244         SnortSnprintfAppend((char *)buffer, PROTO_BUFFER_SIZE,
  245                       "%s\n"
  246                       "Port/Proto Count: %d\n"
  247                       "Port/Proto Range: %d:%d\n",
  248                       inet_ntoa(ip2),
  249                       proto->u_port_count,
  250                       proto->low_p,
  251                       proto->high_p);
  252     }
  253 
  254     dsize = SnortStrnlen((const char *)buffer, PROTO_BUFFER_SIZE);
  255     *total_size += dsize;
  256 
  257     /*
  258     **  Set the payload size.  This is protocol independent.
  259     */
  260     g_tmp_pkt->dsize = dsize;
  261 
  262     return 0;
  263 }
  264 
  265 static int LogPortscanAlert(Packet *p, const char *msg, uint32_t event_id,
  266         uint32_t event_ref, uint32_t gen_id, uint32_t sig_id)
  267 {
  268     char timebuf[TIMEBUF_SIZE];
  269     sfaddr_t* src_addr;
  270     sfaddr_t* dst_addr;
  271 
  272     if(!p->iph_api)
  273         return -1;
  274 
  275     /* Do not log if being suppressed */
  276     src_addr = GET_SRC_IP(p);
  277     dst_addr = GET_DST_IP(p);
  278 
  279     if( sfthreshold_test(gen_id, sig_id, src_addr, dst_addr, p->pkth->ts.tv_sec) )
  280     {
  281         return 0;
  282     }
  283 
  284     ts_print((struct timeval *)&p->pkth->ts, timebuf);
  285 
  286     fprintf(g_logfile, "Time: %s\n", timebuf);
  287 
  288     if(event_id)
  289         fprintf(g_logfile, "event_id: %u\n", event_id);
  290     else
  291         fprintf(g_logfile, "event_ref: %u\n", event_ref);
  292 
  293     fprintf(g_logfile, "%s ", inet_ntoa(GET_SRC_ADDR(p)));
  294     fprintf(g_logfile, "-> %s %s\n", inet_ntoa(GET_DST_ADDR(p)), msg);
  295     fprintf(g_logfile, "%.*s\n", p->dsize, p->data);
  296 
  297     fflush(g_logfile);
  298 
  299     return 0;
  300 }
  301 
  302 static int GeneratePSSnortEvent(Packet *p,uint32_t gen_id,uint32_t sig_id,
  303         uint32_t sig_rev, uint32_t class, uint32_t priority, const char *msg)
  304 {
  305     unsigned int event_id;
  306 
  307     event_id = GenerateSnortEvent(p,gen_id,sig_id,sig_rev,class,priority,msg);
  308 
  309     if(g_logfile)
  310         LogPortscanAlert(p, msg, event_id, 0, gen_id, sig_id);
  311 
  312     return event_id;
  313 }
  314 
  315 /*
  316 **  NAME
  317 **    GenerateOpenPortEvent::
  318 */
  319 /**
  320 **  We have to generate open port events differently because we tag these
  321 **  to the original portscan event.
  322 **
  323 **  @return int
  324 **
  325 **  @retval 0 success
  326 */
  327 static int GenerateOpenPortEvent(Packet *p, uint32_t gen_id, uint32_t sig_id,
  328         uint32_t sig_rev, uint32_t class, uint32_t pri,
  329         uint32_t event_ref, struct timeval *event_time, const char *msg)
  330 {
  331     Event event;
  332 
  333     /*
  334     **  This means that we logged an open port, but we don't have a event
  335     **  reference for it, so we don't log a snort event.  We still keep
  336     **  track of it though.
  337     */
  338     if(!event_ref)
  339         return 0;
  340 
  341     /* reset the thresholding subsystem checks for this packet */
  342     sfthreshold_reset();
  343 
  344 #if !defined(FEAT_OPEN_APPID)
  345     SetEvent(&event, gen_id, sig_id, sig_rev, class, pri, event_ref);
  346 #else /* defined(FEAT_OPEN_APPID) */
  347     SetEvent(&event, gen_id, sig_id, sig_rev, class, pri, event_ref, NULL);
  348 #endif /* defined(FEAT_OPEN_APPID) */
  349     //CallAlertFuncs(p,msg,NULL,&event);
  350 
  351     event.ref_time.tv_sec  = event_time->tv_sec;
  352     event.ref_time.tv_usec = event_time->tv_usec;
  353 
  354     if(p)
  355     {
  356         /*
  357          * Do threshold test for suppression and thresholding.  We have to do it
  358          * here since these are tagged packets, which aren't subject to thresholding,
  359          * but we want to do it for open port events.
  360          */
  361         if( sfthreshold_test(gen_id, sig_id, GET_SRC_IP(p),
  362                             GET_DST_IP(p), p->pkth->ts.tv_sec) )
  363         {
  364             return 0;
  365         }
  366 
  367         CallLogFuncs(p,msg,NULL,&event);
  368     }
  369     else
  370     {
  371         return -1;
  372     }
  373 
  374     if(g_logfile)
  375         LogPortscanAlert(p, msg, 0, event_ref, gen_id, sig_id);
  376 
  377     return event.event_id;
  378 }
  379 
  380 /*
  381 **  NAME
  382 **    MakeOpenPortInfo::
  383 */
  384 /**
  385 **  Write out the open ports info for open port alerts.
  386 **
  387 **  @return integer
  388 */
  389 static int MakeOpenPortInfo(PS_PROTO *proto, u_char *buffer, u_int *total_size,
  390          void *user)
  391 {
  392     int dsize;
  393 
  394     if(!total_size || !buffer)
  395         return -1;
  396 
  397     dsize = (g_tmp_pkt->max_dsize - *total_size);
  398 
  399     if(dsize < PROTO_BUFFER_SIZE)
  400        return -1;
  401 
  402     SnortSnprintf((char *)buffer, PROTO_BUFFER_SIZE,
  403                   "Open Port: %u\n", *((unsigned short *)user));
  404 
  405     dsize = SnortStrnlen((const char *)buffer, PROTO_BUFFER_SIZE);
  406     *total_size += dsize;
  407 
  408     /*
  409     **  Set the payload size.  This is protocol independent.
  410     */
  411     g_tmp_pkt->dsize = dsize;
  412 
  413     return 0;
  414 }
  415 
  416 /*
  417 **  NAME
  418 **    MakePortscanPkt::
  419 */
  420 /*
  421 **  We have to create this fake packet so portscan data can be passed
  422 **  through the unified output.
  423 **
  424 **  We want to copy the network and transport layer headers into our
  425 **  fake packet.
  426 **
  427 */
  428 static int MakePortscanPkt(PS_PKT *ps_pkt, PS_PROTO *proto, int proto_type,
  429         void *user)
  430 {
  431     unsigned int ip_size = 0;
  432     Packet* p = (Packet *)ps_pkt->pkt;
  433     EncodeFlags flags = ENC_FLAG_NET;
  434 
  435     if (!IsIP(p))
  436         return -1;
  437 
  438     if ( !ps_pkt->reverse_pkt )
  439         flags |= ENC_FLAG_FWD;
  440 
  441     if (p != g_tmp_pkt)
  442     {
  443 #if defined(HAVE_DAQ_ADDRESS_SPACE_ID) && defined(DAQ_VERSION) && DAQ_VERSION > 6
  444       DAQ_PktHdr_t phdr;
  445       memcpy(&phdr, &p->pkth, sizeof(*p->pkth));
  446       if (p->pkth->flags & DAQ_PKT_FLAG_REAL_ADDRESSES)
  447       {
  448         phdr.flags &= ~(DAQ_PKT_FLAG_REAL_SIP_V6 | DAQ_PKT_FLAG_REAL_DIP_V6);
  449         if (flags & ENC_FLAG_FWD)
  450         {
  451           phdr.flags |= phdr.flags & (DAQ_PKT_FLAG_REAL_SIP_V6 | DAQ_PKT_FLAG_REAL_DIP_V6);
  452           phdr.real_sIP = p->pkth->real_sIP;
  453           phdr.real_dIP = p->pkth->real_dIP;
  454         }
  455         else
  456         {
  457           if (p->pkth->flags & DAQ_PKT_FLAG_REAL_SIP_V6)
  458             phdr.flags |= DAQ_PKT_FLAG_REAL_DIP_V6;
  459           if (p->pkth->flags & DAQ_PKT_FLAG_REAL_DIP_V6)
  460             phdr.flags |= DAQ_PKT_FLAG_REAL_SIP_V6;
  461           phdr.real_sIP = p->pkth->real_dIP;
  462           phdr.real_dIP = p->pkth->real_sIP;
  463         }
  464 
  465       }
  466       Encode_Format_With_DAQ_Info(flags, p, g_tmp_pkt, PSEUDO_PKT_PS, &phdr, 0);
  467 #elif defined(HAVE_DAQ_ACQUIRE_WITH_META) && defined(DAQ_VERSION) && DAQ_VERSION > 6
  468       Encode_Format_With_DAQ_Info(flags, p, g_tmp_pkt, PSEUDO_PKT_PS, 0);
  469 #else
  470         Encode_Format(flags, p, g_tmp_pkt, PSEUDO_PKT_PS);
  471 #endif
  472     }
  473 
  474     switch (proto_type)
  475     {
  476         case PS_PROTO_TCP:
  477             g_tmp_pkt->ps_proto = IPPROTO_TCP;
  478             break;
  479         case PS_PROTO_UDP:
  480             g_tmp_pkt->ps_proto = IPPROTO_UDP;
  481             break;
  482         case PS_PROTO_ICMP:
  483             g_tmp_pkt->ps_proto = IPPROTO_ICMP;
  484             break;
  485         case PS_PROTO_IP:
  486             g_tmp_pkt->ps_proto = IPPROTO_IP;
  487             break;
  488         case PS_PROTO_OPEN_PORT:
  489             g_tmp_pkt->ps_proto = GET_IPH_PROTO(p);
  490             break;
  491         default:
  492             return -1;
  493     }
  494 
  495     if(IS_IP4(p))
  496     {
  497         ((IPHdr*)g_tmp_pkt->iph)->ip_proto = IPPROTO_PS;
  498         g_tmp_pkt->inner_ip4h.ip_proto = IPPROTO_PS;
  499     }
  500     else
  501     {
  502         if ( g_tmp_pkt->raw_ip6h )
  503             ((IP6RawHdr*)g_tmp_pkt->raw_ip6h)->ip6nxt = IPPROTO_PS;
  504         g_tmp_pkt->inner_ip6h.next = IPPROTO_PS;
  505         g_tmp_pkt->ip6h = &g_tmp_pkt->inner_ip6h;
  506     }
  507 
  508     switch(proto_type)
  509     {
  510         case PS_PROTO_TCP:
  511         case PS_PROTO_UDP:
  512         case PS_PROTO_ICMP:
  513         case PS_PROTO_IP:
  514             if(MakeProtoInfo(proto, (u_char*)g_tmp_pkt->data, &ip_size))
  515                 return -1;
  516 
  517             break;
  518 
  519         case PS_PROTO_OPEN_PORT:
  520             if(MakeOpenPortInfo(proto, (u_char*)g_tmp_pkt->data, &ip_size, user))
  521                 return -1;
  522 
  523             break;
  524 
  525         default:
  526             return -1;
  527     }
  528 
  529     /*
  530     **  Let's finish up the IP header and checksum.
  531     */
  532     Encode_Update(g_tmp_pkt);
  533 
  534     if(IS_IP4(g_tmp_pkt))
  535     {
  536         g_tmp_pkt->inner_ip4h.ip_len = ((IPHdr *)g_tmp_pkt->iph)->ip_len;
  537     }
  538     else if (IS_IP6(g_tmp_pkt))
  539     {
  540         g_tmp_pkt->inner_ip6h.len = htons((uint16_t)ip_size);
  541     }
  542 
  543     return 0;
  544 }
  545 
  546 static int PortscanAlertTcp(Packet *p, PS_PROTO *proto, int proto_type)
  547 {
  548     int iCtr;
  549     unsigned int event_ref;
  550     int portsweep = 0;
  551 
  552     if(!proto)
  553         return -1;
  554 
  555     switch(proto->alerts)
  556     {
  557         case PS_ALERT_ONE_TO_ONE:
  558             event_ref = GeneratePSSnortEvent(p, GENERATOR_PSNG,
  559                     PSNG_TCP_PORTSCAN, 0, 0, 3, PSNG_TCP_PORTSCAN_STR);
  560             break;
  561 
  562         case PS_ALERT_ONE_TO_ONE_DECOY:
  563             event_ref = GeneratePSSnortEvent(p,GENERATOR_PSNG,
  564                     PSNG_TCP_DECOY_PORTSCAN,0,0,3,PSNG_TCP_DECOY_PORTSCAN_STR);
  565             break;
  566 
  567         case PS_ALERT_PORTSWEEP:
  568            event_ref = GeneratePSSnortEvent(p,GENERATOR_PSNG,
  569                    PSNG_TCP_PORTSWEEP, 0, 0, 3, PSNG_TCP_PORTSWEEP_STR);
  570            portsweep = 1;
  571 
  572            break;
  573 
  574         case PS_ALERT_DISTRIBUTED:
  575             event_ref = GeneratePSSnortEvent(p,GENERATOR_PSNG,
  576                     PSNG_TCP_DISTRIBUTED_PORTSCAN, 0, 0, 3,
  577                     PSNG_TCP_DISTRIBUTED_PORTSCAN_STR);
  578             break;
  579 
  580         case PS_ALERT_ONE_TO_ONE_FILTERED:
  581             event_ref = GeneratePSSnortEvent(p,GENERATOR_PSNG,
  582                     PSNG_TCP_FILTERED_PORTSCAN,0,0,3,
  583                     PSNG_TCP_FILTERED_PORTSCAN_STR);
  584             break;
  585 
  586         case PS_ALERT_ONE_TO_ONE_DECOY_FILTERED:
  587             event_ref = GeneratePSSnortEvent(p,GENERATOR_PSNG,
  588                     PSNG_TCP_FILTERED_DECOY_PORTSCAN, 0,0,3,
  589                     PSNG_TCP_FILTERED_DECOY_PORTSCAN_STR);
  590             break;
  591 
  592         case PS_ALERT_PORTSWEEP_FILTERED:
  593            event_ref = GeneratePSSnortEvent(p,GENERATOR_PSNG,
  594                    PSNG_TCP_PORTSWEEP_FILTERED,0,0,3,
  595                    PSNG_TCP_PORTSWEEP_FILTERED_STR);
  596            portsweep = 1;
  597 
  598            return 0;
  599 
  600         case PS_ALERT_DISTRIBUTED_FILTERED:
  601             event_ref = GeneratePSSnortEvent(p,GENERATOR_PSNG,
  602                     PSNG_TCP_FILTERED_DISTRIBUTED_PORTSCAN, 0, 0, 3,
  603                     PSNG_TCP_FILTERED_DISTRIBUTED_PORTSCAN_STR);
  604             break;
  605 
  606         default:
  607             return 0;
  608     }
  609 
  610     /*
  611     **  Set the current event reference information for any open ports.
  612     */
  613     proto->event_ref  = event_ref;
  614     proto->event_time.tv_sec  = p->pkth->ts.tv_sec;
  615     proto->event_time.tv_usec = p->pkth->ts.tv_usec;
  616 
  617     /*
  618     **  Only log open ports for portsweeps after the alert has been
  619     **  generated.
  620     */
  621     if(proto->open_ports_cnt && !portsweep)
  622     {
  623         for(iCtr = 0; iCtr < proto->open_ports_cnt; iCtr++)
  624         {
  625             DAQ_PktHdr_t *pkth = (DAQ_PktHdr_t *)g_tmp_pkt->pkth;
  626             PS_PKT ps_pkt;
  627 
  628             memset(&ps_pkt, 0x00, sizeof(PS_PKT));
  629             ps_pkt.pkt = (void *)p;
  630 
  631             if(MakePortscanPkt(&ps_pkt, proto, PS_PROTO_OPEN_PORT,
  632                         (void *)&proto->open_ports[iCtr]))
  633                 return -1;
  634 
  635             pkth->ts.tv_usec += 1;
  636             GenerateOpenPortEvent(g_tmp_pkt,GENERATOR_PSNG,PSNG_OPEN_PORT,
  637                     0,0,3, proto->event_ref, &proto->event_time,
  638                     PSNG_OPEN_PORT_STR);
  639         }
  640     }
  641 
  642     return 0;
  643 }
  644 
  645 static int PortscanAlertUdp(Packet *p, PS_PROTO *proto, int proto_type)
  646 {
  647     if(!proto)
  648         return -1;
  649 
  650     switch(proto->alerts)
  651     {
  652         case PS_ALERT_ONE_TO_ONE:
  653             GeneratePSSnortEvent(p, GENERATOR_PSNG, PSNG_UDP_PORTSCAN, 0, 0, 3,
  654                     PSNG_UDP_PORTSCAN_STR);
  655             break;
  656 
  657         case PS_ALERT_ONE_TO_ONE_DECOY:
  658             GeneratePSSnortEvent(p,GENERATOR_PSNG,PSNG_UDP_DECOY_PORTSCAN, 0, 0, 3,
  659                     PSNG_UDP_DECOY_PORTSCAN_STR);
  660             break;
  661 
  662         case PS_ALERT_PORTSWEEP:
  663            GeneratePSSnortEvent(p,GENERATOR_PSNG,PSNG_UDP_PORTSWEEP, 0, 0, 3,
  664                     PSNG_UDP_PORTSWEEP_STR);
  665             break;
  666 
  667         case PS_ALERT_DISTRIBUTED:
  668             GeneratePSSnortEvent(p,GENERATOR_PSNG,PSNG_UDP_DISTRIBUTED_PORTSCAN,
  669                     0, 0, 3, PSNG_UDP_DISTRIBUTED_PORTSCAN_STR);
  670             break;
  671 
  672         case PS_ALERT_ONE_TO_ONE_FILTERED:
  673             GeneratePSSnortEvent(p,GENERATOR_PSNG,PSNG_UDP_FILTERED_PORTSCAN,0,0,3,
  674                     PSNG_UDP_FILTERED_PORTSCAN_STR);
  675             break;
  676 
  677         case PS_ALERT_ONE_TO_ONE_DECOY_FILTERED:
  678             GeneratePSSnortEvent(p,GENERATOR_PSNG,PSNG_UDP_FILTERED_DECOY_PORTSCAN,
  679                     0,0,3, PSNG_UDP_FILTERED_DECOY_PORTSCAN_STR);
  680             break;
  681 
  682         case PS_ALERT_PORTSWEEP_FILTERED:
  683            GeneratePSSnortEvent(p,GENERATOR_PSNG,PSNG_UDP_PORTSWEEP_FILTERED,0,0,3,
  684                     PSNG_UDP_PORTSWEEP_FILTERED_STR);
  685             break;
  686 
  687         case PS_ALERT_DISTRIBUTED_FILTERED:
  688             GeneratePSSnortEvent(p,GENERATOR_PSNG,
  689                     PSNG_UDP_FILTERED_DISTRIBUTED_PORTSCAN, 0, 0, 3,
  690                     PSNG_UDP_FILTERED_DISTRIBUTED_PORTSCAN_STR);
  691             break;
  692 
  693         default:
  694             break;
  695     }
  696 
  697     return 0;
  698 }
  699 
  700 static int PortscanAlertIp(Packet *p, PS_PROTO *proto, int proto_type)
  701 {
  702     if(!proto)
  703         return -1;
  704 
  705     switch(proto->alerts)
  706     {
  707         case PS_ALERT_ONE_TO_ONE:
  708             GeneratePSSnortEvent(p, GENERATOR_PSNG, PSNG_IP_PORTSCAN, 0, 0, 3,
  709                     PSNG_IP_PORTSCAN_STR);
  710             break;
  711 
  712         case PS_ALERT_ONE_TO_ONE_DECOY:
  713             GeneratePSSnortEvent(p,GENERATOR_PSNG,PSNG_IP_DECOY_PORTSCAN, 0, 0, 3,
  714                     PSNG_IP_DECOY_PORTSCAN_STR);
  715             break;
  716 
  717         case PS_ALERT_PORTSWEEP:
  718            GeneratePSSnortEvent(p,GENERATOR_PSNG,PSNG_IP_PORTSWEEP, 0, 0, 3,
  719                     PSNG_IP_PORTSWEEP_STR);
  720             break;
  721 
  722         case PS_ALERT_DISTRIBUTED:
  723             GeneratePSSnortEvent(p,GENERATOR_PSNG,PSNG_IP_DISTRIBUTED_PORTSCAN,
  724                     0, 0, 3, PSNG_IP_DISTRIBUTED_PORTSCAN_STR);
  725             break;
  726 
  727         case PS_ALERT_ONE_TO_ONE_FILTERED:
  728             GeneratePSSnortEvent(p,GENERATOR_PSNG,PSNG_IP_FILTERED_PORTSCAN,0,0,3,
  729                     PSNG_IP_FILTERED_PORTSCAN_STR);
  730             break;
  731 
  732         case PS_ALERT_ONE_TO_ONE_DECOY_FILTERED:
  733             GeneratePSSnortEvent(p,GENERATOR_PSNG,PSNG_IP_FILTERED_DECOY_PORTSCAN,
  734                     0,0,3, PSNG_IP_FILTERED_DECOY_PORTSCAN_STR);
  735             break;
  736 
  737         case PS_ALERT_PORTSWEEP_FILTERED:
  738            GeneratePSSnortEvent(p,GENERATOR_PSNG,PSNG_IP_PORTSWEEP_FILTERED,0,0,3,
  739                     PSNG_IP_PORTSWEEP_FILTERED_STR);
  740             break;
  741 
  742         case PS_ALERT_DISTRIBUTED_FILTERED:
  743             GeneratePSSnortEvent(p,GENERATOR_PSNG,
  744                     PSNG_IP_FILTERED_DISTRIBUTED_PORTSCAN, 0, 0, 3,
  745                     PSNG_IP_FILTERED_DISTRIBUTED_PORTSCAN_STR);
  746             break;
  747 
  748         default:
  749             break;
  750     }
  751 
  752     return 0;
  753 }
  754 
  755 static int PortscanAlertIcmp(Packet *p, PS_PROTO *proto, int proto_type)
  756 {
  757     if(!proto)
  758         return -1;
  759 
  760     switch(proto->alerts)
  761     {
  762         case PS_ALERT_PORTSWEEP:
  763            GeneratePSSnortEvent(p,GENERATOR_PSNG,PSNG_ICMP_PORTSWEEP, 0, 0, 3,
  764                     PSNG_ICMP_PORTSWEEP_STR);
  765             break;
  766 
  767         case PS_ALERT_PORTSWEEP_FILTERED:
  768            GeneratePSSnortEvent(p,GENERATOR_PSNG,PSNG_ICMP_PORTSWEEP_FILTERED,0,0,3,
  769                     PSNG_ICMP_PORTSWEEP_FILTERED_STR);
  770             break;
  771 
  772         default:
  773             break;
  774     }
  775 
  776     return 0;
  777 }
  778 
  779 static int PortscanAlert(PS_PKT *ps_pkt, PS_PROTO *proto, int proto_type)
  780 {
  781     Packet *p;
  782 
  783     if(!ps_pkt || !ps_pkt->pkt)
  784         return -1;
  785 
  786     p = (Packet *)ps_pkt->pkt;
  787 
  788     if(proto->alerts == PS_ALERT_OPEN_PORT)
  789     {
  790         if(MakePortscanPkt(ps_pkt, proto, PS_PROTO_OPEN_PORT, (void *)&p->sp))
  791             return -1;
  792 
  793         GenerateOpenPortEvent(g_tmp_pkt,GENERATOR_PSNG,PSNG_OPEN_PORT,0,0,3,
  794                 proto->event_ref, &proto->event_time, PSNG_OPEN_PORT_STR);
  795     }
  796     else
  797     {
  798         if(MakePortscanPkt(ps_pkt, proto, proto_type, NULL))
  799             return -1;
  800 
  801         switch(proto_type)
  802         {
  803             case PS_PROTO_TCP:
  804                 PortscanAlertTcp(g_tmp_pkt, proto, proto_type);
  805                 break;
  806 
  807             case PS_PROTO_UDP:
  808                 PortscanAlertUdp(g_tmp_pkt, proto, proto_type);
  809                 break;
  810 
  811             case PS_PROTO_ICMP:
  812                 PortscanAlertIcmp(g_tmp_pkt, proto, proto_type);
  813                 break;
  814 
  815             case PS_PROTO_IP:
  816                 PortscanAlertIp(g_tmp_pkt, proto, proto_type);
  817                 break;
  818         }
  819     }
  820 
  821     sfthreshold_reset();
  822 
  823     return 0;
  824 }
  825 
  826 static void PortscanDetect(Packet *p, void *context)
  827 {
  828     PS_PKT ps_pkt;
  829     tSfPolicyId policy_id = getNapRuntimePolicy();
  830     PortscanConfig *pPolicyConfig = NULL;
  831     PROFILE_VARS;
  832 
  833     assert(IPH_IS_VALID(p));
  834 
  835     if ( p->packet_flags & PKT_REBUILT_STREAM )
  836         return;
  837 
  838     sfPolicyUserPolicySet (portscan_config, policy_id);
  839     pPolicyConfig = (PortscanConfig *)sfPolicyUserDataGetCurrent(portscan_config);
  840 
  841     if ( pPolicyConfig == NULL )
  842         return;
  843 
  844     portscan_eval_config = pPolicyConfig;
  845 
  846     PREPROC_PROFILE_START(sfpsPerfStats);
  847 
  848     memset(&ps_pkt, 0x00, sizeof(PS_PKT));
  849     ps_pkt.pkt = (void *)p;
  850 
  851     /* See if there is already an exisiting node in the hash table */
  852     ps_detect(&ps_pkt);
  853 
  854     if (ps_pkt.scanner && ps_pkt.scanner->proto.alerts &&
  855        (ps_pkt.scanner->proto.alerts != PS_ALERT_GENERATED))
  856     {
  857         PortscanAlert(&ps_pkt, &ps_pkt.scanner->proto, ps_pkt.proto);
  858     }
  859 
  860     if (ps_pkt.scanned && ps_pkt.scanned->proto.alerts &&
  861         (ps_pkt.scanned->proto.alerts != PS_ALERT_GENERATED))
  862     {
  863         PortscanAlert(&ps_pkt, &ps_pkt.scanned->proto, ps_pkt.proto);
  864     }
  865 
  866     PREPROC_PROFILE_END(sfpsPerfStats);
  867 }
  868 
  869 NORETURN static void FatalErrorNoOption(u_char *option)
  870 {
  871     FatalError("%s(%d) => No argument to '%s' config option.\n",
  872             file_name, file_line, option);
  873 }
  874 
  875 NORETURN static void FatalErrorNoEnd(char *option)
  876 {
  877     FatalError("%s(%d) => No ending brace to '%s' config option.\n",
  878             file_name, file_line, option);
  879 }
  880 
  881 NORETURN static void FatalErrorInvalidArg(char *option)
  882 {
  883     FatalError("%s(%d) => Invalid argument to '%s' config option.\n",
  884             file_name, file_line, option);
  885 }
  886 
  887 NORETURN static void FatalErrorInvalidOption(char *option)
  888 {
  889     FatalError("%s(%d) => Invalid option '%s' to portscan preprocessor.\n",
  890             file_name, file_line, option);
  891 }
  892 
  893 static void ParseProtos(int *protos, char **savptr)
  894 {
  895     char *pcTok;
  896 
  897     if(!protos)
  898         return;
  899 
  900     *protos = 0;
  901 
  902     pcTok = strtok_r(NULL, DELIMITERS, savptr);
  903     while(pcTok)
  904     {
  905         if(!strcasecmp(pcTok, "tcp"))
  906             *protos |= PS_PROTO_TCP;
  907         else if(!strcasecmp(pcTok, "udp"))
  908             *protos |= PS_PROTO_UDP;
  909         else if(!strcasecmp(pcTok, "icmp"))
  910             *protos |= PS_PROTO_ICMP;
  911         else if(!strcasecmp(pcTok, "ip"))
  912             *protos |= PS_PROTO_IP;
  913         else if(!strcasecmp(pcTok, "all"))
  914             *protos = PS_PROTO_ALL;
  915         else if(!strcasecmp(pcTok, TOKEN_ARG_END))
  916             return;
  917         else
  918             FatalErrorInvalidArg("proto");
  919 
  920         pcTok = strtok_r(NULL, DELIMITERS, savptr);
  921     }
  922 
  923     if(!pcTok)
  924         FatalErrorNoEnd("proto");
  925 
  926     return;
  927 }
  928 
  929 static void ParseScanType(int *scan_types, char **savptr)
  930 {
  931     char *pcTok;
  932 
  933     if(!scan_types)
  934         return;
  935 
  936     *scan_types = 0;
  937 
  938     pcTok = strtok_r(NULL, DELIMITERS, savptr);
  939     while(pcTok)
  940     {
  941         if(!strcasecmp(pcTok, "portscan"))
  942             *scan_types |= PS_TYPE_PORTSCAN;
  943         else if(!strcasecmp(pcTok, "portsweep"))
  944             *scan_types |= PS_TYPE_PORTSWEEP;
  945         else if(!strcasecmp(pcTok, "decoy_portscan"))
  946             *scan_types |= PS_TYPE_DECOYSCAN;
  947         else if(!strcasecmp(pcTok, "distributed_portscan"))
  948             *scan_types |= PS_TYPE_DISTPORTSCAN;
  949         else if(!strcasecmp(pcTok, "all"))
  950             *scan_types = PS_TYPE_ALL;
  951         else if(!strcasecmp(pcTok, TOKEN_ARG_END))
  952             return;
  953         else
  954             FatalErrorInvalidArg("scan_type");
  955 
  956         pcTok = strtok_r(NULL, DELIMITERS, savptr);
  957     }
  958 
  959     if(!pcTok)
  960         FatalErrorNoEnd("scan_type");
  961 
  962     return;
  963 }
  964 
  965 static void ParseSenseLevel(int *sense_level, char **savptr)
  966 {
  967     char *pcTok;
  968 
  969     if(!sense_level)
  970         return;
  971 
  972     *sense_level = 0;
  973 
  974     pcTok = strtok_r(NULL, DELIMITERS, savptr);
  975     while(pcTok)
  976     {
  977         if(!strcasecmp(pcTok, "low"))
  978             *sense_level = PS_SENSE_LOW;
  979         else if(!strcasecmp(pcTok, "medium"))
  980             *sense_level = PS_SENSE_MEDIUM;
  981         else if(!strcasecmp(pcTok, "high"))
  982             *sense_level = PS_SENSE_HIGH;
  983         else if(!strcmp(pcTok, TOKEN_ARG_END))
  984             return;
  985         else
  986             FatalErrorInvalidArg("sense_level");
  987 
  988         pcTok = strtok_r(NULL, DELIMITERS, savptr);
  989     }
  990 
  991     if(!pcTok)
  992         FatalErrorNoEnd("sense_level");
  993 
  994     return;
  995 }
  996 
  997 static void ParseIpList(IPSET **ip_list, char *option, char **savptr)
  998 {
  999     char *pcTok;
 1000 
 1001     if(!ip_list)
 1002         return;
 1003 
 1004     pcTok = strtok_r(NULL, TOKEN_ARG_END, savptr);
 1005     if(!pcTok)
 1006         FatalErrorInvalidArg(option);
 1007 
 1008     *ip_list = ipset_new();
 1009     if(!*ip_list)
 1010         FatalError("Failed to initialize ip_list in portscan preprocessor.\n");
 1011 
 1012     if(ipset_parse(*ip_list, pcTok))
 1013         FatalError("%s(%d) => Invalid ip_list to '%s' option.\n",
 1014                 file_name, file_line, option);
 1015 
 1016     return;
 1017 }
 1018 
 1019 static void ParseMemcap(unsigned long *memcap, char **savptr)
 1020 {
 1021     char *pcTok;
 1022     char *p;
 1023 
 1024     if(!memcap)
 1025         return;
 1026 
 1027     *memcap = 0;
 1028 
 1029     pcTok = strtok_r(NULL, DELIMITERS, savptr);
 1030     if(!pcTok)
 1031         FatalErrorNoEnd("memcap");
 1032 
 1033     *memcap = strtoul(pcTok, &p, 10);
 1034 
 1035     if(!*pcTok || *pcTok == '-' || *p)
 1036         FatalErrorInvalidArg("memcap");
 1037 
 1038     pcTok = strtok_r(NULL, DELIMITERS, savptr);
 1039     if(!pcTok)
 1040         FatalErrorNoEnd("memcap");
 1041 
 1042     if(strcmp(pcTok, TOKEN_ARG_END))
 1043         FatalErrorInvalidArg("memcap");
 1044 
 1045     return;
 1046 }
 1047 
 1048 static void PrintIPPortSet(IP_PORT *p)
 1049 {
 1050     char ip_str[80], output_str[80];
 1051     PORTRANGE *pr;
 1052 
 1053     SnortSnprintf(ip_str, sizeof(ip_str), "%s", sfip_to_str(&p->ip.addr));
 1054 
 1055     if(p->notflag)
 1056         SnortSnprintf(output_str, sizeof(output_str), "        !%s", ip_str);
 1057     else
 1058         SnortSnprintf(output_str, sizeof(output_str), "        %s", ip_str);
 1059 
 1060     if (p->ip.bits != 128)
 1061         SnortSnprintfAppend(output_str, sizeof(output_str), "/%d",
 1062                             (sfaddr_family(&p->ip.addr) == AF_INET) ? ((p->ip.bits >= 96) ? p->ip.bits - 96 : -1) : p->ip.bits);
 1063 
 1064     pr=(PORTRANGE*)sflist_first(&p->portset.port_list);
 1065     if ( pr && pr->port_lo != 0 )
 1066         SnortSnprintfAppend(output_str, sizeof(output_str), " : ");
 1067     for( ; pr != 0;
 1068         pr=(PORTRANGE*)sflist_next(&p->portset.port_list) )
 1069     {
 1070         if ( pr->port_lo != 0)
 1071         {
 1072             SnortSnprintfAppend(output_str, sizeof(output_str), "%d", pr->port_lo);
 1073             if ( pr->port_hi != pr->port_lo )
 1074             {
 1075                 SnortSnprintfAppend(output_str, sizeof(output_str), "-%d", pr->port_hi);
 1076             }
 1077             SnortSnprintfAppend(output_str, sizeof(output_str), " ");
 1078         }
 1079     }
 1080     LogMessage("%s\n", output_str);
 1081 }
 1082 
 1083 static void PrintPortscanConf(int detect_scans, int detect_scan_type,
 1084         int sense_level, IPSET *scanner, IPSET *scanned, IPSET *watch,
 1085         unsigned long memcap, char *logpath, int disabled)
 1086 {
 1087     char buf[STD_BUF + 1];
 1088     int proto_cnt = 0;
 1089     IP_PORT *p;
 1090 
 1091     LogMessage("Portscan Detection Config:\n");
 1092     if(disabled)
 1093     {
 1094            LogMessage("    Portscan Detection: INACTIVE\n");
 1095     }
 1096     memset(buf, 0, STD_BUF + 1);
 1097     if (!disabled)
 1098     {
 1099         SnortSnprintf(buf, STD_BUF + 1, "    Detect Protocols:  ");
 1100         if(detect_scans & PS_PROTO_TCP)  { sfsnprintfappend(buf, STD_BUF, "TCP ");  proto_cnt++; }
 1101         if(detect_scans & PS_PROTO_UDP)  { sfsnprintfappend(buf, STD_BUF, "UDP ");  proto_cnt++; }
 1102         if(detect_scans & PS_PROTO_ICMP) { sfsnprintfappend(buf, STD_BUF, "ICMP "); proto_cnt++; }
 1103         if(detect_scans & PS_PROTO_IP)   { sfsnprintfappend(buf, STD_BUF, "IP");    proto_cnt++; }
 1104         LogMessage("%s\n", buf);
 1105     }
 1106 
 1107     if (!disabled)
 1108     {
 1109         memset(buf, 0, STD_BUF + 1);
 1110         SnortSnprintf(buf, STD_BUF + 1, "    Detect Scan Type:  ");
 1111         if(detect_scan_type & PS_TYPE_PORTSCAN)
 1112             sfsnprintfappend(buf, STD_BUF, "portscan ");
 1113         if(detect_scan_type & PS_TYPE_PORTSWEEP)
 1114             sfsnprintfappend(buf, STD_BUF, "portsweep ");
 1115         if(detect_scan_type & PS_TYPE_DECOYSCAN)
 1116             sfsnprintfappend(buf, STD_BUF, "decoy_portscan ");
 1117         if(detect_scan_type & PS_TYPE_DISTPORTSCAN)
 1118             sfsnprintfappend(buf, STD_BUF, "distributed_portscan");
 1119         LogMessage("%s\n", buf);
 1120     }
 1121 
 1122     if (!disabled)
 1123     {
 1124         memset(buf, 0, STD_BUF + 1);
 1125         SnortSnprintf(buf, STD_BUF + 1, "    Sensitivity Level: ");
 1126         if(sense_level == PS_SENSE_HIGH)
 1127             sfsnprintfappend(buf, STD_BUF, "High/Experimental");
 1128         if(sense_level == PS_SENSE_MEDIUM)
 1129             sfsnprintfappend(buf, STD_BUF, "Medium");
 1130         if(sense_level == PS_SENSE_LOW)
 1131             sfsnprintfappend(buf, STD_BUF, "Low");
 1132         LogMessage("%s\n", buf);
 1133     }
 1134 
 1135     LogMessage("    Memcap (in bytes): %lu\n", memcap);
 1136 
 1137     if (!disabled)
 1138     {
 1139         LogMessage("    Number of Nodes:   %ld\n",
 1140             memcap / (sizeof(PS_PROTO)*proto_cnt-1));
 1141 
 1142         if (logpath != NULL)
 1143             LogMessage("    Logfile:           %s\n", logpath);
 1144 
 1145         if(scanner)
 1146         {
 1147             LogMessage("    Ignore Scanner IP List:\n");
 1148             for(p = (IP_PORT*)sflist_first(&scanner->ip_list);
 1149                 p;
 1150                 p = (IP_PORT*)sflist_next(&scanner->ip_list))
 1151             {
 1152                 PrintIPPortSet(p);
 1153             }
 1154         }
 1155 
 1156         if(scanned)
 1157         {
 1158             LogMessage("    Ignore Scanned IP List:\n");
 1159             for(p = (IP_PORT*)sflist_first(&scanned->ip_list);
 1160                 p;
 1161                 p = (IP_PORT*)sflist_next(&scanned->ip_list))
 1162             {
 1163                 PrintIPPortSet(p);
 1164             }
 1165         }
 1166 
 1167         if(watch)
 1168         {
 1169             LogMessage("    Watch IP List:\n");
 1170             for(p = (IP_PORT*)sflist_first(&watch->ip_list);
 1171                 p;
 1172                 p = (IP_PORT*)sflist_next(&watch->ip_list))
 1173             {
 1174                 PrintIPPortSet(p);
 1175             }
 1176         }
 1177     }
 1178 }
 1179 
 1180 static void ParseLogFile(struct _SnortConfig *sc, PortscanConfig *config, char **savptr)
 1181 {
 1182     char *pcTok;
 1183 
 1184     if (config == NULL)
 1185         return;
 1186 
 1187     pcTok = strtok_r(NULL, DELIMITERS, savptr);
 1188     if (pcTok == NULL)
 1189     {
 1190         FatalError("%s(%d) => No ending brace to '%s' config option.\n",
 1191                    file_name, file_line, "logfile");
 1192     }
 1193 
 1194     config->logfile = ProcessFileOption(sc, pcTok);
 1195 
 1196     pcTok = strtok_r(NULL, DELIMITERS, savptr);
 1197     if (pcTok == NULL)
 1198     {
 1199         FatalError("%s(%d) => No ending brace to '%s' config option.\n",
 1200                    file_name, file_line, "logfile");
 1201     }
 1202 
 1203     if (strcmp(pcTok, TOKEN_ARG_END) != 0)
 1204     {
 1205         FatalError("%s(%d) => Invalid argument to '%s' config option.\n",
 1206                    file_name, file_line, "logfile");
 1207     }
 1208 }
 1209 
 1210 #ifdef REG_TEST
 1211 static inline void PrintPORTSCANSize(void)
 1212 {
 1213     LogMessage("\nPORTSCAN Session Size: %lu\n", (long unsigned int)sizeof(PS_TRACKER));
 1214 }
 1215 #endif
 1216 
 1217 static void PortscanInit(struct _SnortConfig *sc, char *args)
 1218 {
 1219     tSfPolicyId policy_id = getParserPolicy(sc);
 1220     PortscanConfig *pPolicyConfig = NULL;
 1221 
 1222 #ifdef REG_TEST
 1223     PrintPORTSCANSize();
 1224 #endif
 1225 
 1226     if (portscan_config == NULL)
 1227     {
 1228         portscan_config = sfPolicyConfigCreate();
 1229         PortscanPacketInit();
 1230 
 1231         AddFuncToPreprocCleanExitList(PortscanCleanExitFunction, NULL, PRIORITY_SCANNER, PP_SFPORTSCAN);
 1232         AddFuncToPreprocResetList(PortscanResetFunction, NULL, PRIORITY_SCANNER, PP_SFPORTSCAN);
 1233         AddFuncToPreprocResetStatsList(PortscanResetStatsFunction, NULL, PRIORITY_SCANNER, PP_SFPORTSCAN);
 1234         AddFuncToPreprocPostConfigList(sc, PortscanOpenLogFile, NULL);
 1235 
 1236 #ifdef PERF_PROFILING
 1237         RegisterPreprocessorProfile("sfportscan", &sfpsPerfStats, 0, &totalPerfStats, NULL);
 1238 #endif
 1239     }
 1240 
 1241     if ((policy_id != 0) && (((PortscanConfig *)sfPolicyUserDataGetDefault(portscan_config)) == NULL))
 1242     {
 1243         ParseError("Portscan: Must configure default policy if other "
 1244                    "policies are going to be configured.");
 1245     }
 1246 
 1247     sfPolicyUserPolicySet (portscan_config, policy_id);
 1248     pPolicyConfig = (PortscanConfig *)sfPolicyUserDataGetCurrent(portscan_config);
 1249     if (pPolicyConfig)
 1250     {
 1251         ParseError("Can only configure sfportscan once.\n");
 1252     }
 1253     pPolicyConfig = (PortscanConfig *)SnortAlloc(sizeof(PortscanConfig));
 1254     if (!pPolicyConfig)
 1255     {
 1256         ParseError("SFPORTSCAN preprocessor: memory allocate failed.\n");
 1257     }
 1258 
 1259     sfPolicyUserDataSetCurrent(portscan_config, pPolicyConfig);
 1260     ParsePortscan(sc, pPolicyConfig, args);
 1261 
 1262     if (policy_id == 0)
 1263     {
 1264         ps_init_hash(pPolicyConfig->memcap);
 1265     }
 1266     else
 1267     {
 1268         pPolicyConfig->memcap = ((PortscanConfig *)sfPolicyUserDataGetDefault(portscan_config))->memcap;
 1269 
 1270         if (pPolicyConfig->logfile != NULL)
 1271         {
 1272             ParseError("Portscan:  logfile can only be configured in "
 1273                        "default policy.\n");
 1274         }
 1275     }
 1276 
 1277     if ( !pPolicyConfig->disabled )
 1278     {
 1279         AddFuncToPreprocList(sc, PortscanDetect, PRIORITY_SCANNER, PP_SFPORTSCAN,
 1280                              PortscanGetProtoBits(pPolicyConfig->detect_scans));
 1281         session_api->enable_preproc_all_ports( sc,
 1282                                                PP_SFPORTSCAN,
 1283                                                PortscanGetProtoBits(pPolicyConfig->detect_scans) );
 1284     }
 1285 }
 1286 
 1287 void SetupSfPortscan(void)
 1288 {
 1289 #ifndef SNORT_RELOAD
 1290     RegisterPreprocessor("sfportscan", PortscanInit);
 1291 #else
 1292     RegisterPreprocessor("sfportscan", PortscanInit, PortscanReload,
 1293                          PortscanReloadVerify, PortscanReloadSwap,
 1294                          PortscanReloadSwapFree);
 1295 #endif
 1296 }
 1297 
 1298 static void ParsePortscan(struct _SnortConfig *sc, PortscanConfig *config, char *args)
 1299 {
 1300     int    sense_level = PS_SENSE_LOW;
 1301     int    protos      = (PS_PROTO_TCP | PS_PROTO_UDP);
 1302     int    scan_types  = PS_TYPE_ALL;
 1303     unsigned long memcap = 1048576;
 1304     IPSET *ignore_scanners = NULL;
 1305     IPSET *ignore_scanned = NULL;
 1306     IPSET *watch_ip = NULL;
 1307     char  *pcTok, *savpcTok = NULL;
 1308     int    iRet;
 1309 
 1310     if (args != NULL)
 1311     {
 1312         pcTok = strtok_r(args, DELIMITERS, &savpcTok);
 1313         //pcTok = strtok(args, DELIMITERS);
 1314         while(pcTok)
 1315         {
 1316             if(!strcasecmp(pcTok, "proto"))
 1317             {
 1318                 pcTok = strtok_r(NULL, DELIMITERS, &savpcTok);
 1319                 //pcTok = strtok(NULL, DELIMITERS);
 1320                 if(!pcTok || strcmp(pcTok, TOKEN_ARG_BEGIN))
 1321                     FatalErrorNoOption((u_char *)"proto");
 1322 
 1323                 ParseProtos(&protos, &savpcTok);
 1324             }
 1325             else if(!strcasecmp(pcTok, "scan_type"))
 1326             {
 1327                 pcTok = strtok_r(NULL, DELIMITERS, &savpcTok);
 1328                 if(!pcTok || strcmp(pcTok, TOKEN_ARG_BEGIN))
 1329                     FatalErrorNoOption((u_char *)"scan_type");
 1330 
 1331                 ParseScanType(&scan_types, &savpcTok);
 1332             }
 1333             else if(!strcasecmp(pcTok, "sense_level"))
 1334             {
 1335                 pcTok = strtok_r(NULL, DELIMITERS, &savpcTok);
 1336                 if(!pcTok || strcmp(pcTok, TOKEN_ARG_BEGIN))
 1337                     FatalErrorNoOption((u_char *)"sense_level");
 1338 
 1339                 ParseSenseLevel(&sense_level, &savpcTok);
 1340             }
 1341             else if(!strcasecmp(pcTok, "ignore_scanners"))
 1342             {
 1343                 pcTok = strtok_r(NULL, DELIMITERS, &savpcTok);
 1344                 if(!pcTok || strcmp(pcTok, TOKEN_ARG_BEGIN))
 1345                     FatalErrorNoOption((u_char *)"ignore_scanners");
 1346 
 1347                 ParseIpList(&ignore_scanners, "ignore_scanners", &savpcTok);
 1348             }
 1349             else if(!strcasecmp(pcTok, "ignore_scanned"))
 1350             {
 1351                 pcTok = strtok_r(NULL, DELIMITERS, &savpcTok);
 1352                 if(!pcTok || strcmp(pcTok, TOKEN_ARG_BEGIN))
 1353                     FatalErrorNoOption((u_char *)"ignore_scanned");
 1354 
 1355                 ParseIpList(&ignore_scanned, "ignore_scanned", &savpcTok);
 1356             }
 1357             else if(!strcasecmp(pcTok, "watch_ip"))
 1358             {
 1359                 pcTok = strtok_r(NULL, DELIMITERS, &savpcTok);
 1360                 if(!pcTok || strcmp(pcTok, TOKEN_ARG_BEGIN))
 1361                     FatalErrorNoOption((u_char *)"watch_ip");
 1362 
 1363                 ParseIpList(&watch_ip, "watch_ip", &savpcTok);
 1364             }
 1365             else if(!strcasecmp(pcTok, "print_tracker"))
 1366             {
 1367                 config->print_tracker = 1;
 1368             }
 1369             else if(!strcasecmp(pcTok, "memcap"))
 1370             {
 1371                 pcTok = strtok_r(NULL, DELIMITERS, &savpcTok);
 1372                 if(!pcTok || strcmp(pcTok, TOKEN_ARG_BEGIN))
 1373                     FatalErrorNoOption((u_char *)"memcap");
 1374 
 1375                 ParseMemcap(&memcap, &savpcTok);
 1376             }
 1377             else if(!strcasecmp(pcTok, "logfile"))
 1378             {
 1379                 pcTok = strtok_r(NULL, DELIMITERS, &savpcTok);
 1380                 if(!pcTok || strcmp(pcTok, TOKEN_ARG_BEGIN))
 1381                     FatalErrorNoOption((u_char *)"logfile");
 1382 
 1383                 ParseLogFile(sc, config, &savpcTok);
 1384             }
 1385             else if(!strcasecmp(pcTok, "include_midstream"))
 1386             {
 1387                 /* Do not ignore packets in sessions picked up mid-stream */
 1388                 config->include_midstream = 1;
 1389             }
 1390             else if(!strcasecmp(pcTok, "detect_ack_scans"))
 1391             {
 1392                 /*
 1393                  *  We will only see ack scan packets if we are looking at sessions that the
 1394                  *    have been flagged as being picked up mid-stream
 1395                  */
 1396                 config->include_midstream = 1;
 1397             }
 1398             else if(!strcasecmp(pcTok, "disabled"))
 1399             {
 1400                 config->disabled = 1;
 1401             }
 1402             else
 1403             {
 1404                 FatalErrorInvalidOption(pcTok);
 1405             }
 1406 
 1407             pcTok = strtok_r(NULL, DELIMITERS, &savpcTok);
 1408         }
 1409     }
 1410 
 1411     iRet = ps_init(sc, config, protos, scan_types, sense_level, ignore_scanners,
 1412                    ignore_scanned, watch_ip, memcap);
 1413     if (iRet)
 1414     {
 1415         if(iRet == -2)
 1416         {
 1417             FatalError("%s(%d) => 'memcap' limit not sufficient to run "
 1418                        "sfportscan preprocessor.  Please increase this "
 1419                        "value or keep the default memory usage.\n",
 1420                        file_name, file_line);
 1421         }
 1422 
 1423         FatalError("Failed to initialize the sfportscan detection module.  "
 1424                    "Please check your configuration before submitting a "
 1425                    "bug.\n");
 1426     }
 1427 
 1428     PrintPortscanConf(protos, scan_types, sense_level, ignore_scanners,
 1429                       ignore_scanned, watch_ip, memcap, config->logfile, config->disabled);
 1430 }
 1431 
 1432 static void PortscanOpenLogFile(struct _SnortConfig *sc, void *data)
 1433 {
 1434     PortscanConfig *pPolicyConfig = (PortscanConfig *)sfPolicyUserDataGetDefault(portscan_config) ;
 1435     if ((  pPolicyConfig== NULL) ||
 1436         (pPolicyConfig->logfile == NULL))
 1437     {
 1438         return;
 1439     }
 1440 
 1441     g_logfile = fopen(pPolicyConfig->logfile, "a+");
 1442     if (g_logfile == NULL)
 1443     {
 1444         FatalError("Portscan log file '%s' could not be opened: %s.\n",
 1445                    pPolicyConfig->logfile, strerror(errno));
 1446     }
 1447 }
 1448 
 1449 static int PortscanFreeConfigPolicy(tSfPolicyUserContextId config,tSfPolicyId policyId, void* pData )
 1450 {
 1451     PortscanConfig *pPolicyConfig = (PortscanConfig *)pData;
 1452     sfPolicyUserDataClear (config, policyId);
 1453     PortscanFreeConfig(pPolicyConfig);
 1454     return 0;
 1455 }
 1456 static void PortscanFreeConfigs(tSfPolicyUserContextId config)
 1457 {
 1458 
 1459     if (config == NULL)
 1460         return;
 1461 
 1462     sfPolicyUserDataFreeIterate (config, PortscanFreeConfigPolicy);
 1463     sfPolicyConfigDelete(config);
 1464 
 1465 }
 1466 
 1467 static void PortscanFreeConfig(PortscanConfig *config)
 1468 {
 1469     if (config == NULL)
 1470         return;
 1471 
 1472     if (config->logfile)
 1473         free(config->logfile);
 1474 
 1475     if (config->ignore_scanners != NULL)
 1476         ipset_free(config->ignore_scanners);
 1477 
 1478     if (config->ignore_scanned != NULL)
 1479         ipset_free(config->ignore_scanned);
 1480 
 1481     if (config->watch_ip != NULL)
 1482         ipset_free(config->watch_ip);
 1483 
 1484     free(config);
 1485 }
 1486 
 1487 static int PortscanGetProtoBits(int detect_scans)
 1488 {
 1489     int proto_bits = PROTO_BIT__IP;
 1490 
 1491     if (detect_scans & PS_PROTO_IP)
 1492     {
 1493         proto_bits |= PROTO_BIT__ICMP;
 1494     }
 1495 
 1496     if (detect_scans & PS_PROTO_UDP)
 1497     {
 1498         proto_bits |= PROTO_BIT__ICMP;
 1499         proto_bits |= PROTO_BIT__UDP;
 1500     }
 1501 
 1502     if (detect_scans & PS_PROTO_ICMP)
 1503         proto_bits |= PROTO_BIT__ICMP;
 1504 
 1505     if (detect_scans & PS_PROTO_TCP)
 1506     {
 1507         proto_bits |= PROTO_BIT__ICMP;
 1508         proto_bits |= PROTO_BIT__TCP;
 1509     }
 1510 
 1511     return proto_bits;
 1512 }
 1513 
 1514 #ifdef SNORT_RELOAD
 1515 static void PortscanReload(struct _SnortConfig *sc, char *args, void **new_config)
 1516 {
 1517     tSfPolicyUserContextId portscan_swap_config = (tSfPolicyUserContextId)*new_config;
 1518     tSfPolicyId policy_id = getParserPolicy(sc);
 1519     PortscanConfig *pPolicyConfig = NULL;
 1520 
 1521     if (!portscan_swap_config)
 1522     {
 1523         portscan_swap_config = sfPolicyConfigCreate();
 1524         *new_config = (void *)portscan_swap_config;
 1525     }
 1526 
 1527     if ((policy_id != 0) && (((PortscanConfig *)sfPolicyUserDataGetDefault(portscan_swap_config)) == NULL))
 1528     {
 1529         ParseError("Portscan: Must configure default policy if other "
 1530                    "policies are going to be configured.");
 1531     }
 1532 
 1533 
 1534     sfPolicyUserPolicySet (portscan_swap_config, policy_id);
 1535 
 1536     pPolicyConfig = (PortscanConfig *)sfPolicyUserDataGetCurrent(portscan_swap_config);
 1537     if (pPolicyConfig)
 1538     {
 1539         ParseError("Can only configure sfportscan once.\n");
 1540     }
 1541 
 1542     pPolicyConfig = (PortscanConfig *)SnortAlloc(sizeof(PortscanConfig));
 1543     if (!pPolicyConfig)
 1544     {
 1545         ParseError("SFPORTSCAN preprocessor: memory allocate failed.\n");
 1546     }
 1547 
 1548 
 1549     sfPolicyUserDataSetCurrent(portscan_swap_config, pPolicyConfig);
 1550     ParsePortscan(sc, pPolicyConfig, args);
 1551 
 1552     if (policy_id != 0)
 1553     {
 1554         pPolicyConfig->memcap = ((PortscanConfig *)sfPolicyUserDataGetDefault(portscan_swap_config))->memcap;
 1555 
 1556         if (pPolicyConfig->logfile != NULL)
 1557         {
 1558             ParseError("Portscan:  logfile can only be configured in "
 1559                        "default policy.\n");
 1560         }
 1561     }
 1562 
 1563     if ( !pPolicyConfig->disabled )
 1564     {
 1565         AddFuncToPreprocList(sc, PortscanDetect, PRIORITY_SCANNER, PP_SFPORTSCAN,
 1566                              PortscanGetProtoBits(pPolicyConfig->detect_scans));
 1567         session_api->enable_preproc_all_ports( sc,
 1568                                               PP_SFPORTSCAN,
 1569                                               PortscanGetProtoBits(pPolicyConfig->detect_scans) );
 1570     }
 1571 }
 1572 
 1573 static bool PortscanReloadAdjust(bool idle, tSfPolicyId raPolicyId, void* userData)
 1574 {
 1575     unsigned max_work = idle ? 512 : 32;
 1576     unsigned long memcap = *(unsigned long *)userData;
 1577     return ps_reload_adjust(memcap, max_work);
 1578 }
 1579 
 1580 static int PortscanReloadVerify(struct _SnortConfig *sc, void *swap_config)
 1581 {
 1582     tSfPolicyUserContextId portscan_swap_config = (tSfPolicyUserContextId)swap_config;
 1583     static unsigned long new_memcap;
 1584     unsigned long old_memcap = ((PortscanConfig *)sfPolicyUserDataGetDefault(portscan_config))->memcap;
 1585     new_memcap = ((PortscanConfig *)sfPolicyUserDataGetDefault(portscan_swap_config))->memcap;
 1586     tSfPolicyId policy_id = getParserPolicy(sc);
 1587 
 1588     if ((portscan_swap_config == NULL) || (((PortscanConfig *)sfPolicyUserDataGetDefault(portscan_swap_config)) == NULL) ||
 1589         (portscan_config == NULL) || (((PortscanConfig *)sfPolicyUserDataGetDefault(portscan_config)) == NULL))
 1590     {
 1591         return 0;
 1592     }
 1593 
 1594     if (old_memcap != new_memcap)
 1595     {
 1596 #ifdef REG_TEST
 1597         if (REG_TEST_FLAG_PORTSCAN_RELOAD & getRegTestFlags())
 1598         {
 1599             printf("portscan memcap old conf : %lu new conf : %lu\n",old_memcap,new_memcap);
 1600         }
 1601 #endif
 1602         /* If memcap is less than  hash overhead bytes, restart is needed */
 1603         if( new_memcap > ps_hash_overhead_bytes())
 1604         {
 1605             ReloadAdjustRegister(sc, "PortscanReload", policy_id, &PortscanReloadAdjust, &new_memcap, NULL);
 1606         }
 1607         else
 1608         {
 1609             ErrorMessage("Portscan Reload: New memcap %lu s lower than  minimum memory needed for hash table %u, and it requires a restart.\n", new_memcap, ps_hash_overhead_bytes());
 1610             return -1;
 1611         }
 1612     }
 1613     return 0;
 1614 }
 1615 
 1616 static void * PortscanReloadSwap(struct _SnortConfig *sc, void  *swap_config)
 1617 {
 1618     tSfPolicyUserContextId portscan_swap_config = (tSfPolicyUserContextId)swap_config;
 1619     tSfPolicyUserContextId old_config = portscan_config;
 1620     bool log_file_swap = false;
 1621 
 1622     if (portscan_swap_config == NULL)
 1623         return NULL;
 1624 
 1625     if ((((PortscanConfig *)sfPolicyUserDataGetDefault(portscan_swap_config))->logfile != NULL) &&
 1626         (((PortscanConfig *)sfPolicyUserDataGetDefault(portscan_config))->logfile != NULL))
 1627     {
 1628         if (strcasecmp(((PortscanConfig *)sfPolicyUserDataGetDefault(portscan_swap_config))->logfile,
 1629                        ((PortscanConfig *)sfPolicyUserDataGetDefault(portscan_config))->logfile) != 0)
 1630         {
 1631             log_file_swap = true;
 1632         }
 1633     }
 1634     else if (((PortscanConfig *)sfPolicyUserDataGetDefault(portscan_swap_config))->logfile != ((PortscanConfig *)sfPolicyUserDataGetDefault(portscan_config))->logfile)
 1635     {
 1636         log_file_swap = true;
 1637     }
 1638 
 1639     if(log_file_swap)
 1640     {
 1641         char *new_logfile = ((PortscanConfig *)sfPolicyUserDataGetDefault(portscan_swap_config))->logfile;
 1642 #ifdef REG_TEST
 1643         char *old_logfile = ((PortscanConfig *)sfPolicyUserDataGetDefault(portscan_config))->logfile;
 1644         if (REG_TEST_FLAG_PORTSCAN_RELOAD & getRegTestFlags())
 1645         {
 1646             printf("portscan Logfile  old: %s , new: %s \n", old_logfile?old_logfile:"NULL", new_logfile?new_logfile:"NULL");
 1647         }
 1648 #endif
 1649         if(g_logfile)
 1650         {
 1651             fclose(g_logfile);
 1652             g_logfile = NULL;
 1653         }
 1654         if(new_logfile)
 1655         {
 1656             g_logfile = fopen(new_logfile, "a");
 1657             if (g_logfile == NULL)
 1658             {
 1659                 FatalError("Portscan log file '%s' could not be opened: %s.\n",
 1660                         new_logfile, strerror(errno));
 1661             }
 1662         }
 1663     }
 1664 
 1665     portscan_config = portscan_swap_config;
 1666     return (void *)old_config;
 1667 }
 1668 
 1669 static void PortscanReloadSwapFree(void *data)
 1670 {
 1671     if (data == NULL)
 1672         return;
 1673 
 1674     PortscanFreeConfigs((tSfPolicyUserContextId)data);
 1675 }
 1676 #endif
 1677