"Fossies" - the Fresh Open Source Software Archive

Member "snort-2.9.17/src/dynamic-preprocessors/appid/luaDetectorApi.c" (16 Oct 2020, 153087 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 "luaDetectorApi.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 ** Copyright (C) 2014-2020 Cisco and/or its affiliates. All rights reserved.
    3 ** Copyright (C) 2005-2013 Sourcefire, Inc.
    4 **
    5 ** This program is free software; you can redistribute it and/or modify
    6 ** it under the terms of the GNU General Public License Version 2 as
    7 ** published by the Free Software Foundation.  You may not use, modify or
    8 ** distribute this program under any other version of the GNU General
    9 ** Public License.
   10 **
   11 ** This program is distributed in the hope that it will be useful,
   12 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
   13 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   14 ** GNU General Public License for more details.
   15 **
   16 ** You should have received a copy of the GNU General Public License
   17 ** along with this program; if not, write to the Free Software
   18 ** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
   19 */
   20 
   21 
   22 /** @defgroup LuaDetectorBaseApi LuaDetectorBaseApi
   23  * This module supports basic API towards Lua detectors.
   24  *@{
   25  */
   26 
   27 #include <stdio.h>
   28 #include <errno.h>
   29 #include <sys/types.h>
   30 #include <sys/stat.h>
   31 #include <unistd.h>
   32 #include <inttypes.h>
   33 #include <assert.h>
   34 
   35 #include "client_app_base.h"
   36 #include "service_base.h"
   37 #include "luaDetectorApi.h"
   38 #include "luaDetectorModule.h"
   39 #include "luaDetectorApi.h"
   40 #include "luaDetectorFlowApi.h"
   41 #include <pcre.h>
   42 #include "httpCommon.h"
   43 #include "sf_multi_mpse.h"
   44 #include "fw_appid.h"
   45 #include "http_url_patterns.h"
   46 #include "service_ssl.h"
   47 #include "hostPortAppCache.h"
   48 #include "appInfoTable.h"
   49 #include "ip_funcs.h"
   50 #include "lengthAppCache.h"
   51 #include "detector_dns.h"
   52 #include "app_forecast.h"
   53 #include "detector_pattern.h"
   54 #include "detector_cip.h"
   55 
   56 #define DETECTOR "Detector"
   57 #define OVECCOUNT 30    /* should be a multiple of 3 */
   58 #define URL_LIST_STEP_SIZE  5000
   59 
   60 typedef enum {
   61     LUA_LOG_CRITICAL = 0,
   62     LUA_LOG_ERR = 1,
   63     LUA_LOG_WARN = 2,
   64     LUA_LOG_NOTICE = 3,
   65     LUA_LOG_INFO = 4,
   66     LUA_LOG_DEBUG = 5,
   67 } LUA_LOG_LEVELS;
   68 
   69 /*static const char * LuaLogLabel = "luaDetectorApi"; */
   70 static ThrottleInfo error_throttleInfo = {0,30,0};
   71 
   72 #ifdef PERF_PROFILING
   73 PreprocStats luaDetectorsPerfStats;
   74 PreprocStats luaCiscoPerfStats;
   75 PreprocStats luaCustomPerfStats;
   76 #endif
   77 
   78 static void FreeDetectorAppUrlPattern(DetectorAppUrlPattern *pattern);
   79 
   80 static DetectorUserData *toDetectorUserData (lua_State *L, int index)
   81 {
   82   DetectorUserData *bar = (DetectorUserData *)lua_touserdata(L, index);
   83   if (bar == NULL) luaL_typerror(L, index, DETECTOR);
   84   return bar;
   85 }
   86 
   87 DetectorUserData *checkDetectorUserData (
   88         lua_State *L,
   89         int index
   90         )
   91 {
   92   DetectorUserData *bar;
   93 
   94   luaL_checktype(L, index, LUA_TUSERDATA);
   95 
   96   bar = (DetectorUserData *)luaL_checkudata(L, index, DETECTOR);
   97   if (bar == NULL)
   98   {
   99       luaL_typerror(L, index, DETECTOR);
  100   }
  101 
  102   return bar;
  103 }
  104 
  105 static DetectorUserData *pushDetectorUserData(lua_State *L)
  106 {
  107   DetectorUserData *bar = (DetectorUserData *)lua_newuserdata(L, sizeof(DetectorUserData));
  108 
  109   if (bar)
  110   {
  111 #ifdef LUA_DETECTOR_DEBUG
  112         _dpd.debugMsg(DEBUG_LOG,"DetectorUserData %p: allocated\n\n",bar);
  113 #endif
  114       memset(bar, 0, sizeof(*bar));
  115 
  116       if ((bar->pDetector = (Detector *)calloc(1, sizeof(Detector))) == NULL)
  117       {
  118           lua_pop(L, -1);
  119 
  120           return NULL;
  121       }
  122 
  123       luaL_getmetatable(L, DETECTOR);
  124       lua_setmetatable(L, -2);
  125 
  126 #ifdef LUA_DETECTOR_DEBUG
  127         _dpd.debugMsg(DEBUG_LOG,"Detector %p: allocated\n\n",bar->pDetector);
  128 #endif
  129   }
  130   return bar;
  131 }
  132 
  133 Detector *createDetector(
  134         lua_State *L,
  135         const char *detectorName
  136         )
  137 {
  138     DetectorUserData *pUserData;
  139     Detector  *detector;
  140 
  141     pUserData = pushDetectorUserData(L);
  142 
  143     if (!pUserData || !pUserData->pDetector)
  144     {
  145         _dpd.errMsg( "Failed to allocate memory.");
  146         return NULL;
  147     }
  148 
  149     detector = pUserData->pDetector;
  150 
  151     lua_pushvalue( L, -1 );     /*create a copy of userData */
  152     detector->detectorUserDataRef = luaL_ref( L, LUA_REGISTRYINDEX );
  153     detector->name = strdup(detectorName);
  154     if (!detector->name)
  155     {
  156         free(pUserData->pDetector);
  157         return NULL;
  158     }
  159 
  160     detector->myLuaState = L;
  161     pthread_mutex_init(&detector->luaReloadMutex, NULL);
  162 
  163     return detector;
  164 }
  165 
  166 
  167 /**must be called only when RNA is exitting.
  168  */
  169 void freeDetector(Detector *detector)
  170 {
  171     tDetectorPackageInfo  *pkg = &detector->packageInfo;
  172 
  173     if (!detector)
  174         return;
  175 
  176     if (detector->server.pServiceElement)
  177     {
  178         free(detector->server.pServiceElement);
  179     }
  180 
  181     if (detector->server.serviceModule.name)
  182     {
  183         free((void *)(detector->server.serviceModule.name));
  184     }
  185 
  186     if (pkg->name)
  187     {
  188         free(pkg->name);
  189     }
  190     if (pkg->client.initFunctionName)
  191     {
  192         free(pkg->client.initFunctionName);
  193     }
  194     if (pkg->client.cleanFunctionName)
  195     {
  196         free(pkg->client.cleanFunctionName);
  197     }
  198     if (pkg->client.validateFunctionName)
  199     {
  200         free(pkg->client.validateFunctionName);
  201     }
  202     if (pkg->server.initFunctionName)
  203     {
  204         free(pkg->server.initFunctionName);
  205     }
  206     if (pkg->server.cleanFunctionName)
  207     {
  208         free(pkg->server.cleanFunctionName);
  209     }
  210     if (pkg->server.validateFunctionName)
  211     {
  212         free(pkg->server.validateFunctionName);
  213     }
  214 
  215     /*The detectorUserData itself is a userdata and therefore be freed by Lua side. */
  216     if (detector->detectorUserDataRef != LUA_REFNIL)
  217     {
  218         DetectorUserData *pUserData;
  219 
  220         lua_rawgeti(detector->myLuaState, LUA_REGISTRYINDEX, detector->detectorUserDataRef);
  221         pUserData = checkDetectorUserData(detector->myLuaState, -1);
  222         if (pUserData)
  223         {
  224             pUserData->pDetector = NULL;
  225         }
  226 
  227         luaL_unref (detector->myLuaState, LUA_REGISTRYINDEX, detector->detectorUserDataRef);
  228         detector->detectorUserDataRef = LUA_REFNIL;
  229     }
  230 
  231     if (detector->callbackFcnName)
  232     {
  233         free(detector->callbackFcnName);
  234     }
  235 
  236     free(detector->name);
  237     free(detector->validatorBuffer);
  238 
  239 #ifdef LUA_DETECTOR_DEBUG
  240     _dpd.debugMsg(DEBUG_LOG,"Detector %p: freed\n\n",detector);
  241 #endif
  242     free(detector);
  243 }
  244 
  245 int detector_Callback(
  246         const uint8_t *data,
  247         uint16_t size,
  248         const int dir,
  249         tAppIdData *flowp,
  250         const SFSnortPacket *pkt,
  251         Detector *detector,
  252         const tAppIdConfig *pConfig
  253         )
  254 {
  255     int retValue;
  256     lua_State *myLuaState;
  257     char *callbackFn;
  258     char *detectorName;
  259     PROFILE_VARS;
  260 #ifdef PERF_PROFILING
  261     PreprocStats *pPerfStats1;
  262     PreprocStats *pPerfStats2;
  263 #endif
  264 
  265     if (!data || !flowp || !pkt || !detector)
  266     {
  267         return -10;
  268     }
  269 
  270 #ifdef PERF_PROFILING
  271     if (detector->isCustom)
  272         pPerfStats1 = &luaCustomPerfStats;
  273     else
  274         pPerfStats1 = &luaCiscoPerfStats;
  275     pPerfStats2 = detector->pPerfStats;
  276 #endif
  277     PREPROC_PROFILE_START(luaDetectorsPerfStats);
  278     PREPROC_PROFILE_START((*pPerfStats1));
  279     PREPROC_PROFILE_START((*pPerfStats2));
  280 
  281     myLuaState = detector->myLuaState;
  282     detector->validateParams.data = data;
  283     detector->validateParams.size = size;
  284     detector->validateParams.dir = dir;
  285     detector->validateParams.flowp = flowp;
  286     detector->validateParams.pkt = (SFSnortPacket *)pkt;
  287     callbackFn = detector->callbackFcnName;
  288     detectorName = detector->name;
  289 
  290     /* Bail out if we cannot acquire the lock on the detector.
  291        To avoid bailing out, use recursive mutex instead. */
  292     if( pthread_mutex_trylock(&detector->luaReloadMutex))
  293     {
  294         detector->validateParams.pkt = NULL;
  295         PREPROC_PROFILE_END((*pPerfStats2));
  296         PREPROC_PROFILE_END((*pPerfStats1));
  297         PREPROC_PROFILE_END(luaDetectorsPerfStats);
  298         return -11;
  299     }
  300 
  301     if ((!callbackFn) || !(lua_checkstack(myLuaState, 1)))
  302     {
  303         _dpd.errMsgThrottled(&error_throttleInfo,
  304                              "Detector %s: invalid LUA %s\n", 
  305                              detectorName, lua_tostring(myLuaState, -1));
  306         detector->validateParams.pkt = NULL;
  307         pthread_mutex_unlock(&detector->luaReloadMutex);
  308         PREPROC_PROFILE_END((*pPerfStats2));
  309         PREPROC_PROFILE_END((*pPerfStats1));
  310         PREPROC_PROFILE_END(luaDetectorsPerfStats);
  311         return -10;
  312     }
  313 
  314     lua_getglobal(myLuaState, callbackFn);
  315 
  316 #ifdef LUA_DETECTOR_DEBUG
  317     _dpd.debugMsg(DEBUG_LOG,"Detector %s: Lua Memory usage %d\n", detectorName, lua_gc(myLuaState, LUA_GCCOUNT,0));
  318     _dpd.debugMsg(DEBUG_LOG,"Detector %s: validating\n", detectorName);
  319 #endif
  320     if (lua_pcall(myLuaState, 0, 1, 0 ))
  321     {
  322         _dpd.errMsg("Detector %s: Error validating %s\n", detectorName, lua_tostring(myLuaState, -1));
  323         detector->validateParams.pkt = NULL;
  324         pthread_mutex_unlock(&detector->luaReloadMutex);
  325         PREPROC_PROFILE_END((*pPerfStats2));
  326         PREPROC_PROFILE_END((*pPerfStats1));
  327         PREPROC_PROFILE_END(luaDetectorsPerfStats);
  328         return -10;
  329     }
  330 
  331     /**detectorFlows must be destroyed after each packet is processed.*/
  332     sflist_static_free_all(&allocatedFlowList, freeDetectorFlow);
  333 
  334     /* retrieve result */
  335     if (!lua_isnumber(myLuaState, -1))
  336     {
  337         _dpd.errMsg("Detector %s: Validator returned non-numeric value\n", detectorName);
  338         detector->validateParams.pkt = NULL;
  339         pthread_mutex_unlock(&detector->luaReloadMutex);
  340         PREPROC_PROFILE_END((*pPerfStats2));
  341         PREPROC_PROFILE_END((*pPerfStats1));
  342         PREPROC_PROFILE_END(luaDetectorsPerfStats);
  343         retValue = -10;
  344     }
  345 
  346     retValue = lua_tonumber(myLuaState, -1);
  347     lua_pop(myLuaState, 1);  /* pop returned value */
  348     /*lua_settop(myLuaState, 0); */
  349 
  350 #ifdef LUA_DETECTOR_DEBUG
  351     _dpd.debugMsg(DEBUG_LOG,"Detector %s: Validator returned %d\n", detectorName, retValue);
  352 #endif
  353 
  354     detector->validateParams.pkt = NULL;
  355 
  356     pthread_mutex_unlock(&detector->luaReloadMutex);
  357     PREPROC_PROFILE_END((*pPerfStats2));
  358     PREPROC_PROFILE_END((*pPerfStats1));
  359     PREPROC_PROFILE_END(luaDetectorsPerfStats);
  360 
  361     return retValue;
  362 }
  363 
  364 static int Detector_registerClientCallback(lua_State *L)
  365 {
  366     tAppId appId;
  367     const char *callback;
  368     Detector *detector;
  369     int index = 1;
  370 
  371     DetectorUserData *detectorUserData = checkDetectorUserData(L, index++);
  372     appId = lua_tonumber(L, index++);
  373     callback = lua_tostring(L, index++);
  374 
  375     if (!detectorUserData || !callback)
  376     {
  377         lua_pushnumber(L, -1);
  378         return 1;   /*number of results */
  379     }
  380 
  381     detector = detectorUserData->pDetector;
  382 
  383     if (!(detector->callbackFcnName = strdup(callback)))
  384     {
  385         lua_pushnumber(L, -1);
  386         return 1;
  387     }
  388     appSetClientDetectorCallback(detector_Callback, appId, detector, detector->pAppidNewConfig);
  389 
  390     lua_pushnumber(L, 0);
  391     return 1;
  392 }
  393 
  394 static int Detector_registerServiceCallback(lua_State *L)
  395 {
  396     tAppId appId;
  397     const char *callback;
  398     Detector *detector;
  399     int index = 1;
  400 
  401     DetectorUserData *detectorUserData = checkDetectorUserData(L, index++);
  402     appId = lua_tonumber(L, index++);
  403     callback = lua_tostring(L, index++);
  404 
  405     if (!detectorUserData || !callback)
  406     {
  407         lua_pushnumber(L, -1);
  408         return 1;   /*number of results */
  409     }
  410 
  411     detector = detectorUserData->pDetector;
  412 
  413     if (!(detector->callbackFcnName = strdup(callback)))
  414     {
  415         lua_pushnumber(L, -1);
  416         return 1;
  417     }
  418     appSetServiceDetectorCallback(detector_Callback, appId, detector, detector->pAppidNewConfig);
  419 
  420     lua_pushnumber(L, 0);
  421     return 1;
  422 }
  423 
  424 /*converts Luastring to C compatible string. */
  425 static int storeLuaString(const char *LuaString, char **CString)
  426 {
  427     char *string = *CString;
  428 
  429     if (!LuaString)
  430     {
  431         return 0;
  432     }
  433 
  434     *CString = strdup(LuaString);
  435     if (*CString == NULL)
  436     {
  437         *CString = string;
  438         return -1;
  439     }
  440     if (string)
  441     {
  442         free(string);
  443     }
  444 
  445     return 0;
  446 }
  447 
  448 /*check service element, Allocate if necessary */
  449 int checkServiceElement(
  450         Detector *detector
  451         )
  452 {
  453     if (!detector->server.pServiceElement)
  454     {
  455         detector->server.pServiceElement = calloc(1, sizeof(*detector->server.pServiceElement));
  456         if (!detector->server.pServiceElement)
  457         {
  458             return 0;
  459         }
  460         detector->server.pServiceElement->name = detector->server.serviceModule.name;
  461     }
  462 
  463     return 1;
  464 }
  465 
  466 /**Creates a new detector instance. Creates a new detector instance and leaves the instance
  467  * on stack. This is the first call by a lua detector to create and instance. Later calls
  468  * provide the detector instance.
  469  *
  470  * @param Lua_State* - Lua state variable.
  471  * @param serviceName/stack - name of service
  472  * @param pValidator/stack - service validator function name
  473  * @param pFini/stack - service clean exit function name
  474  * @return int - Number of elements on stack, which should be 1 if success 0 otherwise.
  475  * @return detector - a detector instance on stack if successful
  476  */
  477 
  478 static int service_init(lua_State *L)
  479 {
  480     const char *pValidator;
  481     const char *pServiceName;
  482     const char *pFini;
  483     Detector *detector;
  484 
  485     DetectorUserData *detectorUserData = checkDetectorUserData(L, 1);
  486     pServiceName = lua_tostring(L, 2);
  487     pValidator = lua_tostring(L, 3);
  488     pFini = lua_tostring(L, 4);
  489 
  490     if ((!detectorUserData) || (!pServiceName) || (!pValidator) || (!pFini))
  491     {
  492         return 0;
  493     }
  494 
  495     detector = detectorUserData->pDetector;
  496 
  497     lua_getglobal(L, pValidator);
  498     lua_getglobal(L, pFini);
  499     if (!(lua_isfunction(L, -1)) || !(lua_isfunction(L, -2)))
  500     {
  501         _dpd.errMsg("%s: attempted setting validator/fini to non-function\n",detector->server.serviceModule.name);
  502         lua_pop(L, 2);
  503         return 0;
  504     }
  505 
  506     lua_pop(L, 2);
  507 
  508     /*old value is preserved so no error checks needed. */
  509     if (!detector->server.serviceModule.name)
  510         storeLuaString(pServiceName, (char **)&detector->server.serviceModule.name);
  511     storeLuaString(pValidator, &detector->packageInfo.server.validateFunctionName);
  512     storeLuaString(pFini, &detector->packageInfo.server.cleanFunctionName);
  513 
  514     /*create a ServiceElement */
  515     if (checkServiceElement(detector))
  516     {
  517         detector->server.pServiceElement->validate = validateAnyService;
  518         detector->server.pServiceElement->userdata = detector;
  519 
  520         detector->server.pServiceElement->detectorType = DETECTOR_TYPE_DECODER;
  521     }
  522 
  523 #ifdef LUA_DETECTOR_DEBUG
  524     _dpd.debugMsg(DEBUG_LOG,"allocated detector = %p\n",detector);
  525 #endif
  526     return 1;
  527 }
  528 
  529 /**Register a pattern for fast pattern matching. Lua detector calls this function to register a pattern
  530  * for fast pattern matching. This is similar to registerPattern in traditional C detector.
  531  *
  532  * @param Lua_State* - Lua state variable.
  533  * @param detector/stack - detector object
  534  * @param protocol/stack - protocol type. Values can be {tcp=6, udp=17 }
  535  * @param pattern/stack - pattern string.
  536  * @param size/stack - number of bytes in pattern
  537  * @param position/stack -  position offset where to start matching pattern.
  538  * @return int - Number of elements on stack, which is always 1.
  539  * @return status/stack - 0 if successful, -1 otherwise.
  540  */
  541 static int service_registerPattern(
  542         lua_State *L
  543         )
  544 {
  545     int protocol;
  546     size_t size;
  547     const char *pattern;
  548     unsigned int position;
  549     Detector *detector;
  550     int index = 1;
  551 
  552     DetectorUserData *detectorUserData = checkDetectorUserData(L, index++);
  553     protocol = lua_tonumber(L, index++);
  554     pattern = lua_tostring(L, index++);
  555     size = lua_tonumber(L, index++);
  556     position = lua_tonumber(L, index++);
  557 
  558     if ((pattern == NULL) || (detectorUserData == NULL))
  559     {
  560         lua_pushnumber(L, -1);
  561         return 1;   /*number of results */
  562     }
  563 
  564     detector = detectorUserData->pDetector;
  565 
  566     /*Note: we can not give callback into lua directly so we have to */
  567     /*give a local callback function, which will do demuxing and */
  568     /*then call lua callback function. */
  569 
  570     /*mpse library does not hold reference to pattern therefore we dont need to allocate it. */
  571 
  572     ServiceRegisterPatternDetector(validateAnyService, protocol, (uint8_t *)pattern,
  573                                    size, position, detector, detector->server.serviceModule.name);
  574 
  575     lua_pushnumber(L, 0);
  576     return 1;   /*number of results */
  577 }
  578 
  579 static int common_registerAppId(
  580         lua_State *L
  581         )
  582 {
  583     unsigned int appId;
  584     Detector *detector;
  585     int index = 1;
  586 
  587     DetectorUserData *detectorUserData = checkDetectorUserData(L, index++);
  588     appId = lua_tonumber(L, index++);
  589 
  590     if (detectorUserData == NULL)
  591     {
  592         lua_pushnumber(L, -1);
  593         return 1;   /*number of results */
  594     }
  595 
  596     detector = detectorUserData->pDetector;
  597 
  598     if (detector->packageInfo.server.initFunctionName)
  599         appSetLuaServiceValidator(validateAnyService, appId, APPINFO_FLAG_SERVICE_ADDITIONAL, (void *)detector);
  600     if (detector->packageInfo.client.initFunctionName)
  601         appSetLuaClientValidator(validateAnyClientApp, appId, APPINFO_FLAG_CLIENT_ADDITIONAL, (void *)detector);
  602 
  603     appInfoSetActive(appId, true);
  604 
  605     lua_pushnumber(L, 0);
  606     return 1;   /*number of results */
  607 }
  608 
  609 static int Detector_htons(
  610         lua_State *L
  611         )
  612 {
  613     unsigned short aShort;
  614     DetectorUserData *detectorUserData = checkDetectorUserData(L, 1);
  615     aShort = lua_tonumber(L, 2);
  616 
  617     if (detectorUserData == NULL)
  618     {
  619         lua_pushnumber(L, -1);
  620         return 1;
  621     }
  622 
  623     lua_pushnumber(L, htons(aShort));
  624     return 1;
  625 }
  626 
  627 static int Detector_htonl(
  628         lua_State *L
  629         )
  630 {
  631     unsigned int anInt;
  632 
  633     DetectorUserData *detectorUserData = checkDetectorUserData(L, 1);
  634     anInt = lua_tonumber(L, 2);
  635 
  636     if (detectorUserData == NULL)
  637     {
  638         lua_pushnumber(L, -1);
  639         return 1;
  640     }
  641 
  642     lua_pushnumber(L, htonl(anInt));
  643     return 1;
  644 }
  645 
  646 /**Logs messages from detectors into wherever /etc/syslog.conf directs them.
  647  * examples are:
  648  *     detector:log(DC.logLevel.warning, 'a warning')
  649  *
  650  *@param level - level of message. See DetectorCommon for enumeration.
  651  *@param message - message to be logged.
  652  */
  653 static int Detector_logMessage(
  654         lua_State *L
  655         )
  656 {
  657     unsigned int level;
  658     const char *message;
  659     Detector *detector;
  660     DetectorUserData *detectorUserData = checkDetectorUserData(L, 1);
  661 
  662     level = lua_tonumber(L, 2);
  663     message = lua_tostring(L, 3);
  664 
  665     if (detectorUserData == NULL)
  666     {
  667         return 0;
  668     }
  669 
  670     detector = detectorUserData->pDetector;
  671 
  672     switch (level)
  673     {
  674         case LUA_LOG_CRITICAL:
  675             _dpd.fatalMsg("%s:%s\n",detector->server.serviceModule.name, message);
  676             break;
  677         case LUA_LOG_ERR:
  678             _dpd.errMsg("%s:%s\n",detector->server.serviceModule.name, message);
  679             break;
  680         case LUA_LOG_WARN:
  681             _dpd.errMsg("%s:%s\n",detector->server.serviceModule.name, message);
  682             break;
  683         case LUA_LOG_NOTICE:
  684             _dpd.logMsg("%s:%s\n",detector->server.serviceModule.name, message);
  685             break;
  686         case LUA_LOG_INFO:
  687             _dpd.logMsg("%s:%s\n",detector->server.serviceModule.name, message);
  688             break;
  689         case LUA_LOG_DEBUG:
  690             DEBUG_WRAP(DebugMessage(DEBUG_APPID, "%s:%s\n",detector->server.serviceModule.name, message););
  691             break;
  692         default:
  693             break;
  694     }
  695 
  696     return 0;
  697 }
  698 
  699 /** Analyze application payload
  700  *
  701  * @param Lua_State* - Lua state variable.
  702  * @param detector/stack - detector object
  703  * @param major/stack - major number of application
  704  * @param minor/stack - minor number of application
  705  * @param flags/stack - any flags
  706  * @return int - Number of elements on stack, which is always 0.
  707  */
  708 static int service_analyzePayload(
  709         lua_State *L
  710         )
  711 {
  712     unsigned int payloadId;
  713     Detector *detector;
  714     DetectorUserData *detectorUserData = checkDetectorUserData(L, 1);
  715 
  716     payloadId = lua_tonumber(L, 2);
  717 
  718     /*check inputs and whether this function is called in context of a */
  719     /*packet */
  720     if (!detectorUserData || !detectorUserData->pDetector->validateParams.pkt)
  721     {
  722         lua_pushnumber(L, -1);
  723         return 1;
  724     }
  725 
  726     detector = detectorUserData->pDetector;
  727 
  728     detector->validateParams.flowp->payloadAppId = payloadId;
  729 
  730     lua_pushnumber(L, 0);
  731     return 1;
  732 }
  733 
  734 /**Design notes: Due to following two design limitations:
  735  * a. lua validate functions, known only at runtime, can not be wrapped inside unique
  736  *    C functions at runtime and
  737  * b. core engine can not call lua functions directly.
  738  *
  739  * There must be a common validate function in C that in turn calls relevent Lua functions.
  740  * Right now there is only one detector so there is a one-to-one mapping, but the framework
  741  * will have to support multiple detectors in production environment. Core engine API will be
  742  * changed to take an additional void* that will be used to call only a unique detector.
  743  */
  744 /*Common validate function that wraps lua based validate functions. */
  745 int validateAnyService(ServiceValidationArgs *args)
  746 {
  747     int retValue;
  748     lua_State *myLuaState = NULL;
  749     const char *serverName;
  750     struct _Detector *detector = args->userdata;
  751     PROFILE_VARS;
  752 #ifdef PERF_PROFILING
  753     PreprocStats *pPerfStats1;
  754     PreprocStats *pPerfStats2;
  755 #endif
  756 
  757     if (!detector)
  758     {
  759         _dpd.errMsg( "invalid LUA parameters");
  760         return SERVICE_ENULL;
  761     }
  762 
  763 #ifdef PERF_PROFILING
  764     if (detector->isCustom)
  765         pPerfStats1 = &luaCustomPerfStats;
  766     else
  767         pPerfStats1 = &luaCiscoPerfStats;
  768     pPerfStats2 = detector->pPerfStats;
  769 #endif
  770     PREPROC_PROFILE_START(luaDetectorsPerfStats);
  771     PREPROC_PROFILE_START((*pPerfStats1));
  772     PREPROC_PROFILE_START((*pPerfStats2));
  773 
  774     myLuaState = detector->myLuaState;
  775     detector->validateParams.data = args->data;
  776     detector->validateParams.size = args->size;
  777     detector->validateParams.dir = args->dir;
  778     detector->validateParams.flowp = args->flowp;
  779     detector->validateParams.pkt = args->pkt;
  780     serverName = detector->name;
  781 
  782     /*Note: Some frequently used header fields may be extracted and stored in detector for */
  783     /*better performance. */
  784 
  785     pthread_mutex_lock(&detector->luaReloadMutex);
  786     if ((!detector->packageInfo.server.validateFunctionName) || !(lua_checkstack(myLuaState, 1)))
  787     {
  788         _dpd.errMsgThrottled(&error_throttleInfo,
  789                              "server %s: invalid LUA %s\n",
  790                              serverName, lua_tostring(myLuaState, -1));
  791         detector->validateParams.pkt = NULL;
  792         pthread_mutex_unlock(&detector->luaReloadMutex);
  793         PREPROC_PROFILE_END((*pPerfStats2));
  794         PREPROC_PROFILE_END((*pPerfStats1));
  795         PREPROC_PROFILE_END((luaDetectorsPerfStats));
  796         return SERVICE_ENULL;
  797     }
  798 
  799     lua_getglobal(myLuaState, detector->packageInfo.server.validateFunctionName);
  800 
  801 #ifdef LUA_DETECTOR_DEBUG
  802     _dpd.debugMsg(DEBUG_LOG,"server %s: Lua Memory usage %d\n",serverName, lua_gc(myLuaState, LUA_GCCOUNT,0));
  803     _dpd.debugMsg(DEBUG_LOG,"server %s: validating\n",serverName);
  804 #endif
  805     if (lua_pcall(myLuaState, 0, 1, 0 ))
  806     {
  807         /*Runtime Lua errors are suppressed in production code since detectors are written for efficiency */
  808         /*and with defensive minimum checks. Errors are dealt as exceptions that dont impact processing */
  809         /*by other detectors or future packets by the same detector. */
  810         _dpd.errMsg("server %s: error validating %s\n",serverName, lua_tostring(myLuaState, -1));
  811         detector->validateParams.pkt = NULL;
  812         pthread_mutex_unlock(&detector->luaReloadMutex);
  813         PREPROC_PROFILE_END((*pPerfStats2));
  814         PREPROC_PROFILE_END((*pPerfStats1));
  815         PREPROC_PROFILE_END(luaDetectorsPerfStats);
  816         return SERVICE_ENULL;
  817     }
  818 
  819     /**detectorFlows must be destroyed after each packet is processed.*/
  820     sflist_static_free_all(&allocatedFlowList, freeDetectorFlow);
  821 
  822     /* retrieve result */
  823     if (!lua_isnumber(myLuaState, -1))
  824     {
  825         _dpd.errMsg("server %s:  validator returned non-numeric value\n",serverName);
  826         detector->validateParams.pkt = NULL;
  827         pthread_mutex_unlock(&detector->luaReloadMutex);
  828         PREPROC_PROFILE_END((*pPerfStats2));
  829         PREPROC_PROFILE_END((*pPerfStats1));
  830         PREPROC_PROFILE_END(luaDetectorsPerfStats);
  831         return SERVICE_ENULL;
  832     }
  833 
  834     retValue = lua_tonumber(myLuaState, -1);
  835     lua_pop(myLuaState, 1);  /* pop returned value */
  836     /*lua_settop(myLuaState, 0); */
  837 
  838 #ifdef LUA_DETECTOR_DEBUG
  839     _dpd.debugMsg(DEBUG_LOG,"server %s: Validator returned %d\n",serverName, retValue);
  840 #endif
  841 
  842     detector->validateParams.pkt = NULL;
  843     pthread_mutex_unlock(&detector->luaReloadMutex);
  844 
  845     PREPROC_PROFILE_END((*pPerfStats2));
  846     PREPROC_PROFILE_END((*pPerfStats1));
  847     PREPROC_PROFILE_END(luaDetectorsPerfStats);
  848     return retValue;
  849 }
  850 
  851 
  852 /**design: dont store serviceId in detector structure since a single detector
  853  * can get serviceId for multiple protocols. For example SIP which gets Id for RTP and
  854  * SIP services.
  855  */
  856 
  857 /**Get service id from database, given service name. Lua detectors call this function at init time
  858  * get get a service Id (an integer) from database.
  859  *
  860  * @param Lua_State* - Lua state variable.
  861  * @param detector/stack - detector object
  862  * @param serviceName/stack - Name of service
  863  * @return int - Number of elements on stack, which is always 1.
  864  * @return serviceId/stack - serviceId if successful, -1 otherwise.
  865  */
  866 static int service_getServiceId(
  867         lua_State *L
  868         )
  869 {
  870     DetectorUserData *detectorUserData = checkDetectorUserData(L, 1);
  871 
  872     if (detectorUserData == NULL)
  873     {
  874         lua_pushnumber(L, 0);
  875         return 1;
  876     }
  877 
  878     lua_pushnumber(L, detectorUserData->pDetector->server.serviceId);
  879     return 1;
  880 }
  881 
  882 /**
  883  * Design Notes: In these APIs, three different AppID contexts - pAppidNewConfig, pAppidOldConfig
  884  * and pAppidActiveConfig are used. pAppidNewConfig is used in APIs related to the loading of the
  885  * detector such as service_addPorts(), client_registerPattern(), etc. A detector is loaded either
  886  * during reload or at initialization. Use of pAppidNewConfig will cause the data structures related
  887  * to the detector such as service ports, patterns, etc to be saved in the new AppID context.
  888  *
  889  * The new AppID context becomes active at the end of initialization or at reload swap.
  890  * FinalizeLuaModules() is called at this time, which changes all the detectors' pAppidActiveConfig
  891  * references to the new context. Also, pAppidOldConfig will be changed to point to the previous
  892  * AppID context. In the packet processing APIs such as service_addService(), client_addUser(), etc.
  893  * pAppidActiveConfig is used.
  894  *
  895  * In the cleanup APIs such as service_removePorts(), Detector_fini(), etc., data structures in the
  896  * old AppID conext need to be freed. Therefore, pAppidOldConfig is used in these APIs.
  897  */
  898 
  899 /**Add port for a given service. Lua detectors call this function to register ports on which a
  900  * given service is expected to run.
  901  *
  902  * @param Lua_State* - Lua state variable.
  903  * @param detector/stack - detector object
  904  * @param protocol/stack - protocol type. Values can be {tcp=6, udp=17 }
  905  * @param port/stack - port number to register.
  906  * @return int - Number of elements on stack, which is always 1.
  907  * @return status/stack - 0 if successful, -1 otherwise.
  908  */
  909 static int service_addPorts(
  910         lua_State *L
  911         )
  912 {
  913     RNAServiceValidationPort pp;
  914     Detector *detector;
  915     DetectorUserData *detectorUserData = checkDetectorUserData(L, 1);
  916 
  917     pp.proto = lua_tonumber(L, 2);
  918     pp.port = lua_tonumber(L, 3);
  919     pp.reversed_validation = lua_tonumber(L, 5);
  920     pp.validate = &validateAnyService;
  921 
  922     if (!detectorUserData || ((pp.proto != IPPROTO_UDP) && (pp.proto != IPPROTO_TCP))
  923             || !pp.port)
  924     {
  925         lua_pushnumber(L, -1);
  926         return 1;
  927     }
  928 
  929     detector = detectorUserData->pDetector;
  930 
  931     if (ServiceAddPort(&pp, &detector->server.serviceModule, (void*)detector, detector->pAppidNewConfig))
  932     {
  933         lua_pushnumber(L, -1);
  934         return 1;
  935     }
  936 
  937     detector->server.pServiceElement->ref_count++;
  938 
  939     lua_pushnumber(L, 0);
  940     return 1;
  941 }
  942 
  943 /**Remove all ports for a given service. Lua detectors call this function to remove ports for this service
  944  * when exiting. This function is not used currently by any detectors.
  945  *
  946  * @param Lua_State* - Lua state variable.
  947  * @param detector/stack - detector object
  948  * @return int - Number of elements on stack, which is always 1.
  949  * @return status/stack - 0 if successful, -1 otherwise.
  950  */
  951 static int service_removePorts(
  952         lua_State *L
  953         )
  954 {
  955     /*RNAServiceValidationFCN validate */
  956     /*from initAPI */
  957     Detector *detector;
  958     DetectorUserData *detectorUserData = checkDetectorUserData(L, 1);
  959 
  960     if (detectorUserData == NULL)
  961     {
  962         lua_pushnumber(L, -1);
  963         return 1;
  964     }
  965 
  966     detector = detectorUserData->pDetector;
  967 
  968     detectorRemoveAllPorts(detector, detector->pAppidOldConfig);
  969 
  970     lua_pushnumber(L, 0);
  971     return 1;
  972 }
  973 
  974 /**Shared function between Lua API and RNA core.
  975  */
  976 void detectorRemoveAllPorts (
  977                              Detector *detector,
  978                              tAppIdConfig *pConfig
  979         )
  980 {
  981     ServiceRemovePorts(&validateAnyService, (void*)detector, pConfig);
  982 }
  983 
  984 /**Set service name. Lua detectors call this function to set service name. It is preferred to set service name
  985  * when a detector is created. Afterwards there is rarely a need to change service name.
  986  *
  987  * @param Lua_State* - Lua state variable.
  988  * @param detector/stack - detector object
  989  * @param serviceName/stack - Name of service
  990  * @return int - Number of elements on stack, which is always 1.
  991  * @return status/stack - 0 if successful, -1 otherwise.
  992  */
  993 static int service_setServiceName(
  994         lua_State *L
  995         )
  996 {
  997 #if 0
  998     Detector *detector;
  999     char *serviceName;
 1000     int retValue = -1;
 1001     DetectorUserData *detectorUserData = checkDetectorUserData(L, 1);
 1002 
 1003     serviceName = (char *)lua_tostring(L, 2);
 1004 
 1005     if (!detectorUserData || !serviceName)
 1006     {
 1007         lua_pushnumber(L, -1);
 1008         return 1;
 1009     }
 1010 
 1011     detector = detectorUserData->pDetector;
 1012 
 1013     retValue = storeLuaString(serviceName, (char **)&detector->server.serviceModule.name);
 1014 
 1015     lua_pushnumber(L, retValue);
 1016     return 1;
 1017 #else
 1018     lua_pushnumber(L, 0);
 1019     return 1;
 1020 #endif
 1021 }
 1022 
 1023 /**Get service name. Lua detectors call this function to get service name. There is
 1024  * rarely a need to change service name.
 1025  *
 1026  * @param Lua_State* - Lua state variable.
 1027  * @param detector/stack - detector object
 1028  * @return int - Number of elements on stack, which is always 1.
 1029  * @return serviceName/stack - service name if successful, nil otherwise.
 1030  */
 1031 static int service_getServiceName(
 1032         lua_State *L
 1033         )
 1034 {
 1035     Detector *detector;
 1036     DetectorUserData *detectorUserData = checkDetectorUserData(L, 1);
 1037 
 1038     if (detectorUserData == NULL)
 1039     {
 1040         return 0;
 1041     }
 1042 
 1043     detector = detectorUserData->pDetector;
 1044 
 1045     lua_pushstring(L, detector->server.serviceModule.name);
 1046     return 1;
 1047 }
 1048 
 1049 /**Is this a customer defined detector. Lua detectors can call this function to verify if the detector
 1050  * was created by Sourcefire or not.
 1051  *
 1052  * @param Lua_State* - Lua state variable.
 1053  * @param detector/stack - detector object
 1054  * @return int - Number of elements on stack, which is always 1.
 1055  * @return integer/stack - -1 if failed, 0 if sourcefire created, 1 otherwise.
 1056  */
 1057 static int service_isCustomDetector(
 1058         lua_State *L
 1059         )
 1060 {
 1061     Detector *detector;
 1062     DetectorUserData *detectorUserData = checkDetectorUserData(L, 1);
 1063 
 1064     if (detectorUserData == NULL)
 1065     {
 1066         lua_pushnumber(L, -1);
 1067         return 1;
 1068     }
 1069 
 1070     detector = detectorUserData->pDetector;
 1071 
 1072     lua_pushnumber(L, detector->isCustom);
 1073     return 1;
 1074 }
 1075 
 1076 /**Set service validator Lua function name. Lua detectors use this function to set a lua function name
 1077  * as service validator function. It is preferred to set validatorname when a detector is created.
 1078  * Afterwards there is rarely a need to change service name.
 1079  *
 1080  * @param Lua_State* - Lua state variable.
 1081  * @param detector/stack - detector object
 1082  * @param validatorName/stack - Name of service validator
 1083  * @return int - Number of elements on stack, which is always 0.
 1084  */
 1085 static int service_setValidator(
 1086         lua_State *L
 1087         )
 1088 {
 1089     Detector *detector;
 1090     DetectorUserData *detectorUserData = checkDetectorUserData(L, 1);
 1091     const char *pValidator;
 1092 
 1093     if (detectorUserData == NULL)
 1094     {
 1095         lua_pushnumber(L, -1);
 1096         return 1;
 1097     }
 1098 
 1099     detector = detectorUserData->pDetector;
 1100 
 1101     pValidator = lua_tostring(L, 2);
 1102     lua_getglobal(L, pValidator);
 1103     if (!lua_isfunction(L, -1))
 1104     {
 1105         _dpd.errMsg("%s: attempted setting validator to non-function\n",detector->server.serviceModule.name);
 1106         lua_pop(L, 1);
 1107         lua_pushnumber(L, -1);
 1108         return 1;
 1109     }
 1110 
 1111     lua_pop(L, 1);
 1112 
 1113     if (storeLuaString(pValidator, &detector->packageInfo.server.validateFunctionName) == -1)
 1114     {
 1115         _dpd.errMsg( "memory allocation failure");
 1116         lua_pushnumber(L, -1);
 1117         return 1;
 1118     }
 1119 
 1120     lua_pushnumber(L, 0);
 1121     return 1;
 1122 }
 1123 
 1124 /** Add data (validator function name) to a flow. Detector use this function when confirming a flow
 1125  * belongs to this service.
 1126  *
 1127  * @param Lua_State* - Lua state variable.
 1128  * @param detector/stack - detector object
 1129  * @param sourcePort/stack - Source port number.
 1130  * @return int - Number of elements on stack, which is always 0.
 1131  */
 1132 static int service_addDataId(
 1133         lua_State *L
 1134         )
 1135 {
 1136     Detector *detector;
 1137     uint16_t sport;
 1138     DetectorUserData *detectorUserData = checkDetectorUserData(L, 1);
 1139 
 1140     sport = lua_tonumber(L, 2);
 1141 
 1142     /*check inputs and whether this function is called in context of a */
 1143     /*packet */
 1144     if (!detectorUserData || !checkServiceElement(detectorUserData->pDetector)
 1145             || !detectorUserData->pDetector->validateParams.pkt)
 1146     {
 1147         lua_pushnumber(L, -1);
 1148         return 1;
 1149     }
 1150 
 1151     detector = detectorUserData->pDetector;
 1152 
 1153     AppIdFlowdataAddId(detector->validateParams.flowp, sport, detector->server.pServiceElement);
 1154 
 1155     lua_pushnumber(L, 0);
 1156     return 1;
 1157 }
 1158 
 1159 /** Add service id to a flow. Positive identification by a detector.
 1160  *
 1161  * @param Lua_State* - Lua state variable.
 1162  * @param detector/stack - detector object
 1163  * @param serviceId/stack - id of service postively identified on this flow.
 1164  * @param vendorName/stack - name of vendor of service. This is optional.
 1165  * @param version/stack - version of service. This is optional.
 1166  * @return int - Number of elements on stack, which is always 1.
 1167  * @return int/stack - values from enum SERVICE_RETCODE
 1168  */
 1169 static int service_addService(
 1170         lua_State *L
 1171         )
 1172 {
 1173     char *vendor, *version;
 1174     unsigned int serviceId, retValue = SERVICE_ENULL;
 1175     Detector *detector;
 1176     DetectorUserData *detectorUserData = checkDetectorUserData(L, 1);
 1177 
 1178     serviceId = lua_tonumber(L, 2);
 1179     vendor = (char *)luaL_optstring(L, 3, NULL);
 1180     version = (char *)luaL_optstring(L, 4, NULL);
 1181 
 1182     /*check inputs (vendor and version may be null) and whether this function is */
 1183     /*called in context of a packet */
 1184     if (!detectorUserData || !checkServiceElement(detectorUserData->pDetector)
 1185            || !detectorUserData->pDetector->validateParams.pkt)
 1186     {
 1187         lua_pushnumber(L, SERVICE_ENULL);
 1188         return 1;
 1189     }
 1190 
 1191     detector = detectorUserData->pDetector;
 1192 
 1193     /*Phase2 - discuss RNAServiceSubtype will be maintained on lua side therefore the last parameter on the following call is NULL. */
 1194     /*Subtype is not displayed on DC at present. */
 1195     retValue = AppIdServiceAddService(detector->validateParams.flowp, detector->validateParams.pkt,
 1196             detector->validateParams.dir, detector->server.pServiceElement,
 1197             appGetAppFromServiceId(serviceId, detector->pAppidActiveConfig), vendor, version, NULL, NULL);
 1198 
 1199     lua_pushnumber(L, retValue);
 1200     return 1;
 1201 }
 1202 
 1203 /**Function confirms the flow is not running this service.
 1204  *
 1205  * @param Lua_State* - Lua state variable.
 1206  * @param detector/stack - detector object
 1207  * @return int - Number of elements on stack, which is always 1.
 1208  * @return int/stack - values from enum SERVICE_RETCODE
 1209  */
 1210 static int service_failService(
 1211         lua_State *L
 1212         )
 1213 {
 1214     unsigned int retValue = SERVICE_ENULL;
 1215     Detector *detector;
 1216     DetectorUserData *detectorUserData = checkDetectorUserData(L, 1);
 1217 
 1218     /*check inputs (vendor and version may be null) and whether this function is */
 1219     /*called in context of a packet */
 1220     if (!detectorUserData || !checkServiceElement(detectorUserData->pDetector)
 1221            || !detectorUserData->pDetector->validateParams.pkt)
 1222     {
 1223         lua_pushnumber(L, SERVICE_ENULL);
 1224         return 1;
 1225     }
 1226 
 1227     detector = detectorUserData->pDetector;
 1228 
 1229     retValue = AppIdServiceFailService(detector->validateParams.flowp, detector->validateParams.pkt,
 1230                                        detector->validateParams.dir, detector->server.pServiceElement, APPID_SESSION_DATA_NONE, detector->pAppidActiveConfig, NULL);
 1231 
 1232     lua_pushnumber(L, retValue);
 1233     return 1;
 1234 
 1235 }
 1236 
 1237 /**Detector use this function to indicate the flow may belong to this flow.
 1238  *
 1239  * @param Lua_State* - Lua state variable.
 1240  * @param detector/stack - detector object
 1241  * @return int - Number of elements on stack, which is always 1.
 1242  * @return int/stack - values from enum SERVICE_RETCODE
 1243  */
 1244 static int service_inProcessService(
 1245         lua_State *L
 1246         )
 1247 {
 1248     unsigned int retValue = -1;
 1249     Detector *detector;
 1250     DetectorUserData *detectorUserData = checkDetectorUserData(L, 1);
 1251 
 1252     /*check inputs (vendor and version may be null) and whether this function is */
 1253     /*called in context of a packet */
 1254     if (!detectorUserData || !checkServiceElement(detectorUserData->pDetector)
 1255            || !detectorUserData->pDetector->validateParams.pkt)
 1256     {
 1257         lua_pushnumber(L, SERVICE_ENULL);
 1258         return 1;
 1259     }
 1260 
 1261     detector = detectorUserData->pDetector;
 1262 
 1263     retValue = AppIdServiceInProcess(detector->validateParams.flowp, detector->validateParams.pkt,
 1264                                      detector->validateParams.dir, detector->server.pServiceElement, NULL);
 1265 
 1266     lua_pushnumber(L, retValue);
 1267     return 1;
 1268 }
 1269 
 1270 /**Detector use this function to indicate error in service identification.
 1271  *
 1272  * @param Lua_State* - Lua state variable.
 1273  * @param detector/stack - detector object
 1274  * @return int - Number of elements on stack, which is always 1.
 1275  * @return int/stack - values from enum SERVICE_RETCODE
 1276  */
 1277 static int service_inCompatibleData(
 1278         lua_State *L
 1279         )
 1280 {
 1281     unsigned int retValue = SERVICE_ENULL;
 1282     Detector *detector;
 1283     DetectorUserData *detectorUserData = checkDetectorUserData(L, 1);
 1284 
 1285     /*check inputs (vendor and version may be null) and whether this function is */
 1286     /*called in context of a packet */
 1287     if (!detectorUserData || !checkServiceElement(detectorUserData->pDetector)
 1288            || !detectorUserData->pDetector->validateParams.pkt)
 1289     {
 1290         lua_pushnumber(L, SERVICE_ENULL);
 1291         return 1;
 1292     }
 1293 
 1294     detector = detectorUserData->pDetector;
 1295 
 1296     retValue = AppIdServiceIncompatibleData(detector->validateParams.flowp, detector->validateParams.pkt,
 1297                                             detector->validateParams.dir, detector->server.pServiceElement,
 1298                                             APPID_SESSION_DATA_NONE, detector->pAppidActiveConfig, NULL);
 1299 
 1300     lua_pushnumber(L, retValue);
 1301     return 1;
 1302 }
 1303 
 1304 /** Get size of current packet. It should be noted that due to restrictions on sharing pointers
 1305  * between C and Lua, packet data is maintained on C side. Lua side can get specific fields, run
 1306  * memcmp and pattern matching on packet data.
 1307  *
 1308  * @param Lua_State* - Lua state variable.
 1309  * @param detector/stack - detector object
 1310  * @return int - Number of elements on stack, which is always 1 if successful, 0 otherwise.
 1311  * @return packetSize/stack - size of packet on stack, if successful.
 1312  */
 1313 static int Detector_getPacketSize(
 1314         lua_State *L
 1315         )
 1316 {
 1317     Detector *detector;
 1318     DetectorUserData *detectorUserData = checkDetectorUserData(L, 1);
 1319 
 1320     if (detectorUserData == NULL)
 1321     {
 1322         return 0;
 1323     }
 1324 
 1325     detector = detectorUserData->pDetector;
 1326 
 1327     lua_pushnumber(L, detector->validateParams.size);
 1328     return 1;
 1329 }
 1330 
 1331 /**Get packet direction. A flow/session maintains initiater and responder sides. A packet direction
 1332  * is determined wrt to the original initiater.
 1333  *
 1334  * @param Lua_State* - Lua state variable.
 1335  * @param detector/stack - detector object
 1336  * @return int - Number of elements on stack, which is always 1 if successful, 0 otherwise.
 1337  * @return packetDir/stack - direction of packet on stack, if successful.
 1338  */
 1339 static int Detector_getPacketDir(
 1340         lua_State *L
 1341         )
 1342 {
 1343     Detector *detector;
 1344     DetectorUserData *detectorUserData = checkDetectorUserData(L, 1);
 1345 
 1346     if (detectorUserData == NULL)
 1347     {
 1348         /*can not return 0 in case of error, since 0 can be a valid value. */
 1349         return 0;
 1350     }
 1351 
 1352     detector = detectorUserData->pDetector;
 1353 
 1354     lua_pushnumber(L, detector->validateParams.dir);
 1355     return 1;
 1356 }
 1357 
 1358 /**Perform a pcre match with grouping. A simple regular expression match with no grouping
 1359  * can also be performed.
 1360  *
 1361  * @param Lua_State* - Lua state variable.
 1362  * @param detector/stack - detector object
 1363  * @return int - Number of group matches.  May be 0 or more.
 1364  * @return matchedStrings/stack - matched strings are pushed on stack starting with group 0.
 1365  *     There may be 0 or more strings.
 1366  */
 1367 static int Detector_getPcreGroups(
 1368         lua_State *L
 1369         )
 1370 {
 1371     Detector *detector;
 1372     char *pattern;
 1373     unsigned int offset;
 1374     pcre *re;
 1375     int ovector[OVECCOUNT];
 1376     const char *error;
 1377     int erroffset;
 1378     int rc, i;
 1379     DetectorUserData *detectorUserData = checkDetectorUserData(L, 1);
 1380 
 1381     pattern = (char *)lua_tostring(L, 2);
 1382     offset = lua_tonumber(L, 3);     /*offset can be zero, no check necessary. */
 1383 
 1384     if ((pattern == NULL) || (detectorUserData == NULL))
 1385     {
 1386         return 0;
 1387     }
 1388 
 1389     detector = detectorUserData->pDetector;
 1390 
 1391     {
 1392         /*compile the regular expression pattern, and handle errors */
 1393         re = pcre_compile(
 1394                 pattern,          /*the pattern */
 1395                 PCRE_DOTALL,      /*default options - dot matches everything including newline */
 1396                 &error,           /*for error message */
 1397                 &erroffset,       /*for error offset */
 1398                 NULL);            /*use default character tables */
 1399 
 1400         if (re == NULL)
 1401         {
 1402             _dpd.errMsg("PCRE compilation failed at offset %d: %s\n",erroffset, error);
 1403             return 0;
 1404         }
 1405 
 1406 
 1407         /*pattern match against the subject string. */
 1408         rc = pcre_exec(
 1409                 re,                                     /*compiled pattern */
 1410                 NULL,                                   /*no extra data */
 1411                 (char *)detector->validateParams.data,  /*subject string */
 1412                 detector->validateParams.size,          /*length of the subject */
 1413                 offset,                                 /*offset 0 */
 1414                 0,                                      /*default options */
 1415                 ovector,                                /*output vector for substring information */
 1416                 OVECCOUNT);                             /*number of elements in the output vector */
 1417 
 1418 
 1419         if (rc < 0)
 1420         {
 1421             /*Matching failed: clubbing PCRE_ERROR_NOMATCH with other errors. */
 1422             pcre_free(re);
 1423             return 0;
 1424         }
 1425 
 1426         /*Match succeded */
 1427 
 1428         /*printf("\nMatch succeeded at offset %d", ovector[0]); */
 1429         pcre_free(re);
 1430 
 1431 
 1432         if (rc == 0)
 1433         {
 1434             /*overflow of matches */
 1435             rc = OVECCOUNT/3;
 1436             /*printf("ovector only has room for %d captured substrings", rc - 1); */
 1437             _dpd.errMsg("ovector only has room for %d captured substrings\n",rc - 1);
 1438         }
 1439     }
 1440 
 1441 
 1442 
 1443     lua_checkstack (L, rc);
 1444     for (i = 0; i < rc; i++)
 1445     {
 1446         /*printf("%2d: %.*s\n", i, , substring_start); */
 1447         lua_pushlstring(L, (char *)detector->validateParams.data + ovector[2*i], ovector[2*i+1] - ovector[2*i]);
 1448     }
 1449 
 1450     return rc;
 1451 }
 1452 
 1453 /**Performs a simple memory comparison.
 1454  *
 1455  * @param Lua_State* - Lua state variable.
 1456  * @param detector/stack - detector object
 1457  * @param pattern/stack - pattern to be matched.
 1458  * @param patternLenght/stack - length of pattern
 1459  * @param offset/stack - offset into packet payload where matching should start.
 1460  *
 1461  * @return int - Number of group matches.  May be 1 if successful, and 0 if error is encountered.
 1462  * @return memCmpResult/stack - returns -1,0,1 based on memcmp result.
 1463  */
 1464 static int Detector_memcmp(
 1465         lua_State *L
 1466         )
 1467 {
 1468     Detector *detector;
 1469     char *pattern;
 1470     unsigned int patternLen;
 1471     unsigned int offset;
 1472     int rc;
 1473     DetectorUserData *detectorUserData = checkDetectorUserData(L, 1);
 1474 
 1475     pattern = (char *)lua_tostring(L, 2);
 1476     patternLen = lua_tonumber(L, 3);
 1477     offset = lua_tonumber(L, 4);     /*offset can be zero, no check necessary. */
 1478 
 1479     if ((detectorUserData == NULL) || (pattern == NULL))
 1480     {
 1481         return 0;
 1482     }
 1483 
 1484     detector = detectorUserData->pDetector;
 1485 
 1486     rc = memcmp((char *)detector->validateParams.data + offset, pattern, patternLen);
 1487 
 1488     lua_checkstack (L, 1);
 1489     lua_pushnumber(L, rc);
 1490     return 1;
 1491 }
 1492 
 1493 /**Get Packet Protocol Type
 1494  *
 1495  * @param Lua_State* - Lua state variable.
 1496  * @return int - Number of elements on stack, which is protocol type if successful, 0 otherwise.
 1497  * @return protocol type TCP or UDP
 1498  */
 1499 static int Detector_getProtocolType (
 1500         lua_State *L
 1501         )
 1502 {
 1503     Detector *detector;
 1504     DetectorUserData *detectorUserData = checkDetectorUserData(L, 1);
 1505 
 1506     if (!detectorUserData || !detectorUserData->pDetector->validateParams.pkt || !IPH_IS_VALID(detectorUserData->pDetector->validateParams.pkt))
 1507     {
 1508         lua_checkstack (L, 1);
 1509         lua_pushnumber(L, 0);
 1510         return 1;
 1511     }
 1512 
 1513     detector = detectorUserData->pDetector;
 1514 
 1515     lua_checkstack (L, 1);
 1516     lua_pushnumber(L, GET_IPH_PROTO(detector->validateParams.pkt));
 1517     return 1;
 1518 }
 1519 
 1520 /**Get source IP address from IP header.
 1521  *
 1522  * @param Lua_State* - Lua state variable.
 1523  * @param detector/stack - detector object
 1524  * @return int - Number of elements on stack, which is 1 if successful, 0 otherwise.
 1525  * @return IPv4/stack - Source IPv4 addresss.
 1526  */
 1527 static int Detector_getPktSrcIPAddr(
 1528         lua_State *L
 1529         )
 1530 {
 1531     Detector *detector;
 1532     sfaddr_t *ipAddr;
 1533     DetectorUserData *detectorUserData = checkDetectorUserData(L, 1);
 1534 
 1535     if (detectorUserData == NULL)
 1536     {
 1537         return 0;
 1538     }
 1539 
 1540     detector = detectorUserData->pDetector;
 1541 
 1542     ipAddr = GET_SRC_IP(detector->validateParams.pkt);
 1543 
 1544     lua_checkstack (L, 1);
 1545     lua_pushnumber(L, sfaddr_get_ip4_value(ipAddr));
 1546     return 1;
 1547 }
 1548 
 1549 /**Get source port number from IP header.
 1550  *
 1551  * @param Lua_State* - Lua state variable.
 1552  * @param detector/stack - detector object
 1553  * @return int - Number of elements on stack, which is 1 if successful, 0 otherwise.
 1554  * @return portNumber/stack - source port number.
 1555  */
 1556 static int Detector_getPktSrcPort(
 1557         lua_State *L
 1558         )
 1559 {
 1560     Detector *detector;
 1561     unsigned int port;
 1562     DetectorUserData *detectorUserData = checkDetectorUserData(L, 1);
 1563 
 1564     if (detectorUserData == NULL)
 1565     {
 1566         return 0;
 1567     }
 1568 
 1569     detector = detectorUserData->pDetector;
 1570 
 1571     port = detector->validateParams.pkt->src_port;
 1572 
 1573     lua_checkstack (L, 1);
 1574     lua_pushnumber(L, port);
 1575     return 1;
 1576 }
 1577 
 1578 /**Get destination port number from IP header.
 1579  *
 1580  * @param Lua_State* - Lua state variable.
 1581  * @param detector/stack - detector object
 1582  * @return int - Number of elements on stack, which is 1 if successful, 0 otherwise.
 1583  * @return portNumber/stack - destination Port number.
 1584  */
 1585 static int Detector_getPktDstPort(
 1586         lua_State *L
 1587         )
 1588 {
 1589     Detector *detector;
 1590     unsigned int port;
 1591     DetectorUserData *detectorUserData = checkDetectorUserData(L, 1);
 1592 
 1593     if (detectorUserData == NULL)
 1594     {
 1595         return 0;
 1596     }
 1597 
 1598     detector = detectorUserData->pDetector;
 1599 
 1600     port = detector->validateParams.pkt->dst_port;
 1601 
 1602     lua_checkstack (L, 1);
 1603     lua_pushnumber(L, port);
 1604     return 1;
 1605 }
 1606 
 1607 /**Get destination IP address from IP header.
 1608  *
 1609  * @param Lua_State* - Lua state variable.
 1610  * @param detector/stack - detector object
 1611  * @return int - Number of elements on stack, which is 1 if successful, 0 otherwise.
 1612  * @return IPv4/stack - destination IPv4 addresss.
 1613  */
 1614 static int Detector_getPktDstIPAddr(
 1615         lua_State *L
 1616         )
 1617 {
 1618     Detector *detector;
 1619     sfaddr_t *ipAddr;
 1620     DetectorUserData *detectorUserData = checkDetectorUserData(L, 1);
 1621 
 1622     if (detectorUserData == NULL)
 1623     {
 1624         return 0;
 1625     }
 1626 
 1627     detector = detectorUserData->pDetector;
 1628 
 1629     ipAddr = GET_DST_IP(detector->validateParams.pkt);
 1630 
 1631     lua_checkstack (L, 1);
 1632     lua_pushnumber(L, sfaddr_get_ip4_value(ipAddr));
 1633     return 1;
 1634 }
 1635 
 1636 
 1637 /**Get packet count. This is used mostly for printing packet sequence
 1638  * number when RNA is being tested with a pcap file.
 1639  *
 1640  * @param Lua_State* - Lua state variable.
 1641  * @param detector/stack - detector object
 1642  * @return int - Number of elements on stack, which is 1 if successful, 0 otherwise.
 1643  * @return packetCount/stack - Total packet processed by RNA.
 1644  */
 1645 static int Detector_getPktCount(
 1646         lua_State *L
 1647         )
 1648 {
 1649     DetectorUserData *detectorUserData = checkDetectorUserData(L, 1);
 1650 
 1651     if (detectorUserData == NULL)
 1652     {
 1653         return 0;
 1654     }
 1655 
 1656     lua_checkstack (L, 1);
 1657     lua_pushnumber(L, app_id_processed_packet_count);
 1658     return 1;
 1659 }
 1660 
 1661 int validateAnyClientApp(
 1662         const uint8_t *data,
 1663         uint16_t size,
 1664         const int dir,
 1665         tAppIdData *flowp,
 1666         SFSnortPacket *pkt,
 1667         Detector *detector,
 1668         const tAppIdConfig *pConfig
 1669         )
 1670 {
 1671     int retValue;
 1672     lua_State *myLuaState;
 1673     char *validateFn;
 1674     char *clientName;
 1675     PROFILE_VARS;
 1676 #ifdef PERF_PROFILING
 1677     PreprocStats *pPerfStats1;
 1678     PreprocStats *pPerfStats2;
 1679 #endif
 1680 
 1681     if (!data || !flowp || !pkt || !detector)
 1682     {
 1683         return CLIENT_APP_ENULL;
 1684     }
 1685 
 1686 #ifdef PERF_PROFILING
 1687     if (detector->isCustom)
 1688         pPerfStats1 = &luaCustomPerfStats;
 1689     else
 1690         pPerfStats1 = &luaCiscoPerfStats;
 1691     pPerfStats2 = detector->pPerfStats;
 1692 #endif
 1693     PREPROC_PROFILE_START(luaDetectorsPerfStats);
 1694     PREPROC_PROFILE_START((*pPerfStats1));
 1695     PREPROC_PROFILE_START((*pPerfStats2));
 1696 
 1697     myLuaState = detector->myLuaState;
 1698     detector->validateParams.data = data;
 1699     detector->validateParams.size = size;
 1700     detector->validateParams.dir = dir;
 1701     detector->validateParams.flowp = flowp;
 1702     detector->validateParams.pkt = (SFSnortPacket *)pkt;
 1703     validateFn = detector->packageInfo.client.validateFunctionName;
 1704     clientName = detector->name;
 1705 
 1706     pthread_mutex_lock(&detector->luaReloadMutex);
 1707     if ((!validateFn) || !(lua_checkstack(myLuaState, 1)))
 1708     {
 1709         _dpd.errMsgThrottled(&error_throttleInfo,
 1710                             "client %s: invalid LUA %s\n",
 1711                            clientName, lua_tostring(myLuaState, -1));
 1712         detector->validateParams.pkt = NULL;
 1713         pthread_mutex_unlock(&detector->luaReloadMutex);
 1714         PREPROC_PROFILE_END((*pPerfStats2));
 1715         PREPROC_PROFILE_END((*pPerfStats1));
 1716         PREPROC_PROFILE_END(luaDetectorsPerfStats);
 1717         return CLIENT_APP_ENULL;
 1718     }
 1719 
 1720     lua_getglobal(myLuaState, validateFn);
 1721 
 1722 #ifdef LUA_DETECTOR_DEBUG
 1723     _dpd.debugMsg(DEBUG_LOG,"client %s: Lua Memory usage %d\n",clientName, lua_gc(myLuaState, LUA_GCCOUNT,0));
 1724     _dpd.debugMsg(DEBUG_LOG,"client %s: validating\n",clientName);
 1725 #endif
 1726     if (lua_pcall(myLuaState, 0, 1, 0 ))
 1727     {
 1728         _dpd.errMsg("client %s: error validating %s\n",clientName, lua_tostring(myLuaState, -1));
 1729         detector->validateParams.pkt = NULL;
 1730         pthread_mutex_unlock(&detector->luaReloadMutex);
 1731         PREPROC_PROFILE_END((*pPerfStats2));
 1732         PREPROC_PROFILE_END((*pPerfStats1));
 1733         PREPROC_PROFILE_END(luaDetectorsPerfStats);
 1734         return SERVICE_ENULL;
 1735     }
 1736 
 1737     /**detectorFlows must be destroyed after each packet is processed.*/
 1738     sflist_static_free_all(&allocatedFlowList, freeDetectorFlow);
 1739 
 1740     /* retrieve result */
 1741     if (!lua_isnumber(myLuaState, -1))
 1742     {
 1743         _dpd.errMsg("client %s:  validator returned non-numeric value\n",clientName);
 1744         detector->validateParams.pkt = NULL;
 1745         pthread_mutex_unlock(&detector->luaReloadMutex);
 1746         PREPROC_PROFILE_END((*pPerfStats2));
 1747         PREPROC_PROFILE_END((*pPerfStats1));
 1748         PREPROC_PROFILE_END(luaDetectorsPerfStats);
 1749         retValue = SERVICE_ENULL;
 1750     }
 1751 
 1752     retValue = lua_tonumber(myLuaState, -1);
 1753     lua_pop(myLuaState, 1);  /* pop returned value */
 1754     /*lua_settop(myLuaState, 0); */
 1755 
 1756 #ifdef LUA_DETECTOR_DEBUG
 1757     _dpd.debugMsg(DEBUG_LOG,"client %s: Validator returned %d\n",clientName, retValue);
 1758 #endif
 1759 
 1760     detector->validateParams.pkt = NULL;
 1761     pthread_mutex_unlock(&detector->luaReloadMutex);
 1762 
 1763     PREPROC_PROFILE_END((*pPerfStats2));
 1764     PREPROC_PROFILE_END((*pPerfStats1));
 1765     PREPROC_PROFILE_END(luaDetectorsPerfStats);
 1766     return retValue;
 1767 }
 1768 
 1769 static int client_registerPattern(lua_State *L)
 1770 {
 1771     int protocol;
 1772     size_t size;
 1773     const char *pattern;
 1774     unsigned int position;
 1775     Detector *detector;
 1776     int index = 1;
 1777 
 1778     DetectorUserData *detectorUserData = checkDetectorUserData(L, index++);
 1779     protocol = lua_tonumber(L, index++);
 1780     pattern = lua_tostring(L, index++);
 1781     size = lua_tonumber(L, index++);
 1782     position = lua_tonumber(L, index++);
 1783 
 1784     if ((pattern == NULL) || (detectorUserData == NULL))
 1785     {
 1786         lua_pushnumber(L, -1);
 1787         return 1;   /*number of results */
 1788     }
 1789 
 1790     detector = detectorUserData->pDetector;
 1791 
 1792     /*Note: we can not give callback into lua directly so we have to */
 1793     /*give a local callback function, which will do demuxing and */
 1794     /*then call lua callback function. */
 1795 
 1796     /*mpse library does not hold reference to pattern therefore we dont need to allocate it. */
 1797 
 1798     detector->client.appModule.userData = detector;
 1799     clientAppLoadForConfigCallback((void *) &(detector->client.appModule), &detector->pAppidNewConfig->clientAppConfig);
 1800     ClientAppRegisterPattern(validateAnyClientApp, protocol, (uint8_t*)pattern, size, position, 0, (void *)detector, &detector->pAppidNewConfig->clientAppConfig);
 1801 
 1802     lua_pushnumber(L, 0);
 1803     return 1;   /*number of results */
 1804 }
 1805 
 1806 /**Creates a new detector instance. Creates a new detector instance and leaves the instance
 1807  * on stack. This is the first call by a lua detector to create and instance. Later calls
 1808  * provide the detector instance.
 1809  *
 1810  * @param Lua_State* - Lua state variable.
 1811  * @param serviceName/stack - name of service
 1812  * @param pValidator/stack - service validator function name
 1813  * @param pFini/stack - service clean exit function name
 1814  * @return int - Number of elements on stack, which should be 1 if success 0 otherwise.
 1815  * @return detector - a detector instance on stack if successful
 1816  */
 1817 
 1818 static int client_init (lua_State *L)
 1819 {
 1820     /*nothing to do */
 1821     return 0;
 1822 }
 1823 
 1824 static int service_addClient (lua_State *L)
 1825 {
 1826     tAppId clientAppId, serviceId;
 1827     const char *version;
 1828     Detector *detector;
 1829     DetectorUserData *detectorUserData = checkDetectorUserData(L, 1);
 1830 
 1831     clientAppId = lua_tonumber(L, 2);
 1832     serviceId = lua_tonumber(L, 3);
 1833     version = lua_tostring(L, 4);
 1834 
 1835     if (!detectorUserData || !detectorUserData->pDetector->validateParams.pkt
 1836             || !version)
 1837     {
 1838         lua_pushnumber(L, -1);
 1839         return 1;
 1840     }
 1841 
 1842     detector = detectorUserData->pDetector;
 1843 
 1844     AppIdAddClientApp(detector->validateParams.pkt, detector->validateParams.dir, detector->pAppidActiveConfig, detector->validateParams.flowp, serviceId, clientAppId, version);
 1845 
 1846     lua_pushnumber(L, 0);
 1847     return 1;
 1848 }
 1849 
 1850 static int client_addApp(
 1851         lua_State *L
 1852         )
 1853 {
 1854     unsigned int serviceId, productId;
 1855     const char *version;
 1856     Detector *detector;
 1857     DetectorUserData *detectorUserData = checkDetectorUserData(L, 1);
 1858 
 1859     serviceId = lua_tonumber(L, 2);
 1860     productId = lua_tonumber(L, 4);
 1861     version = lua_tostring(L, 5);
 1862 
 1863     /*check inputs and whether this function is called in context of a */
 1864     /*packet */
 1865     if (!detectorUserData || !detectorUserData->pDetector->validateParams.pkt
 1866             || !version)
 1867     {
 1868         lua_pushnumber(L, -1);
 1869         return 1;
 1870     }
 1871 
 1872     detector = detectorUserData->pDetector;
 1873 
 1874     if (!detector->client.appModule.api)
 1875     {
 1876         lua_pushnumber(L, -1);
 1877         return 1;
 1878     }
 1879 
 1880     detector->client.appModule.api->add_app(detector->validateParams.pkt, (APPID_SESSION_DIRECTION) detector->validateParams.dir, detector->pAppidActiveConfig,
 1881             detector->validateParams.flowp, appGetAppFromServiceId(serviceId, detector->pAppidActiveConfig), appGetAppFromClientId(productId, detector->pAppidActiveConfig), version);
 1882 
 1883     lua_pushnumber(L, 0);
 1884     return 1;
 1885 }
 1886 
 1887 static int client_addInfo(
 1888         lua_State *L
 1889         )
 1890 {
 1891     const char *info;
 1892     Detector *detector;
 1893     DetectorUserData *detectorUserData = checkDetectorUserData(L, 1);
 1894 
 1895     info = lua_tostring(L, 2);
 1896 
 1897     /*check inputs and whether this function is called in context of a */
 1898     /*packet */
 1899     if (!detectorUserData || !detectorUserData->pDetector->validateParams.pkt
 1900             || !info)
 1901     {
 1902         lua_pushnumber(L, -1);
 1903         return 1;
 1904     }
 1905 
 1906     detector = detectorUserData->pDetector;
 1907 
 1908     if (!detector->client.appModule.api)
 1909     {
 1910         lua_pushnumber(L, -1);
 1911         return 1;
 1912     }
 1913 
 1914     detector->client.appModule.api->add_info(detector->validateParams.flowp, info);
 1915 
 1916     lua_pushnumber(L, 0);
 1917     return 1;
 1918 }
 1919 
 1920 static int client_addUser(
 1921         lua_State *L
 1922         )
 1923 {
 1924     unsigned int serviceId;
 1925     const char *userName;
 1926     Detector *detector;
 1927     DetectorUserData *detectorUserData = checkDetectorUserData(L, 1);
 1928 
 1929     userName = lua_tostring(L, 2);
 1930     serviceId = lua_tonumber(L, 3);
 1931 
 1932     /*check inputs and whether this function is called in context of a */
 1933     /*packet */
 1934     if (!detectorUserData || !detectorUserData->pDetector->validateParams.pkt || !userName)
 1935     {
 1936         lua_pushnumber(L, -1);
 1937         return 1;
 1938     }
 1939 
 1940     detector = detectorUserData->pDetector;
 1941 
 1942     if (!detector->client.appModule.api)
 1943     {
 1944         lua_pushnumber(L, -1);
 1945         return 1;
 1946     }
 1947 
 1948     detector->client.appModule.api->add_user(detector->validateParams.flowp, userName, appGetAppFromServiceId(serviceId, detector->pAppidActiveConfig), 1);
 1949 
 1950     lua_pushnumber(L, 0);
 1951     return 1;
 1952 }
 1953 
 1954 static int client_addPayload(
 1955         lua_State *L
 1956         )
 1957 {
 1958     unsigned int payloadId;
 1959     Detector *detector;
 1960     DetectorUserData *detectorUserData = checkDetectorUserData(L, 1);
 1961 
 1962     payloadId = lua_tonumber(L, 2);
 1963 
 1964     /*check inputs and whether this function is called in context of a */
 1965     /*packet */
 1966     if (!detectorUserData || !detectorUserData->pDetector->validateParams.pkt)
 1967     {
 1968         lua_pushnumber(L, -1);
 1969         return 1;
 1970     }
 1971 
 1972     detector = detectorUserData->pDetector;
 1973 
 1974     if (!detector->client.appModule.api)
 1975     {
 1976         lua_pushnumber(L, -1);
 1977         return 1;
 1978     }
 1979 
 1980     detector->client.appModule.api->add_payload(detector->validateParams.flowp, appGetAppFromPayloadId(payloadId, detector->pAppidActiveConfig));
 1981 
 1982     lua_pushnumber(L, 0);
 1983     return 1;
 1984 }
 1985 
 1986 /**Get flow object from a detector object. The flow object is then used with flowApi.
 1987  * A new copy of flow object is provided with every call. This can be optimized by maintaining
 1988  * a single copy.
 1989  *
 1990  * @param Lua_State* - Lua state variable.
 1991  * @param detector/stack - detector object
 1992  * @return int - Number of elements on stack, which is 1 if successful, 0 otherwise.
 1993  * @return packetCount/stack - Total packet processed by RNA.
 1994  * @todo maintain a single copy and return the same copy with every call to Detector_getFlow().
 1995  */
 1996 static int Detector_getFlow(
 1997         lua_State *L
 1998         )
 1999 {
 2000     DetectorFlowUserData *detectorFlowUserData;
 2001     Detector *detector;
 2002     DetectorUserData *detectorUserData = checkDetectorUserData(L, 1);
 2003 
 2004     /*check inputs and whether this function is called in context of a packet */
 2005     if (!detectorUserData || !detectorUserData->pDetector->validateParams.pkt)
 2006     {
 2007         return 0;
 2008     }
 2009 
 2010     detector = detectorUserData->pDetector;
 2011 
 2012     detectorFlowUserData = pushDetectorFlowUserData(L);
 2013     if (!detectorFlowUserData || !detectorFlowUserData->pDetectorFlow)
 2014     {
 2015         _dpd.errMsg( "Failed to allocate memory.");
 2016         return 0;
 2017     }
 2018 
 2019     detectorFlowUserData->pDetectorFlow->pFlow = detector->validateParams.flowp;
 2020 
 2021 #ifdef LUA_DETECTOR_DEBUG
 2022     _dpd.debugMsg(DEBUG_LOG, "service %s, Detector_getFlow(): allocated DetectorFlow = %p",
 2023             detector->server.serviceModule.name, detectorFlowUserData);
 2024 #endif
 2025     return 1;
 2026 }
 2027 
 2028 int Detector_addHttpPattern(lua_State *L)
 2029 {
 2030     int          index = 1;
 2031 
 2032     /* Verify detector user data and that we are not in packet context */
 2033     DetectorUserData *detectorUserData = checkDetectorUserData(L, index++);
 2034     if (!detectorUserData)
 2035     {
 2036         _dpd.errMsg( "Invalid HTTP detector user data addHttpPattern.");
 2037         return 0;
 2038     }
 2039 
 2040     /* Verify valid pattern type */
 2041     enum httpPatternType pType = (enum httpPatternType) lua_tointeger(L, index++);
 2042     if(pType < HTTP_PAYLOAD || pType > HTTP_URL)
 2043     {
 2044         _dpd.errMsg( "Invalid HTTP pattern type.");
 2045         return 0;
 2046     }
 2047 
 2048     /* Verify valid DHSequence */
 2049     DHPSequence seq  = (DHPSequence) lua_tointeger(L, index++);
 2050     if(seq < SINGLE || seq > USER_AGENT_HEADER)
 2051     {
 2052         _dpd.errMsg( "Invalid HTTP DHP Sequence.");
 2053         return 0;
 2054     }
 2055 
 2056     uint32_t service_id      = lua_tointeger(L, index++);
 2057     uint32_t client_app      = lua_tointeger(L, index++);
 2058     /*uint32_t client_app_type =*/ lua_tointeger(L, index++);
 2059     uint32_t payload         = lua_tointeger(L, index++);
 2060     /*uint32_t payload_type    =*/ lua_tointeger(L, index++);
 2061 
 2062     if (detectorUserData->pDetector->validateParams.pkt)
 2063     {
 2064         _dpd.errMsg("Invalid detector context addHttpPattern: service_id %u; client_app %u; payload %u\n",service_id, client_app, payload);
 2065         return 0;
 2066     }
 2067 
 2068     /* Verify that pattern is a valid string */
 2069     size_t pattern_size = 0;
 2070     uint8_t* pattern_str = (uint8_t*) strdup(lua_tolstring(L, index++, &pattern_size));
 2071     if(pattern_str == NULL || pattern_size == 0)
 2072     {
 2073         _dpd.errMsg( "Invalid HTTP pattern string.");
 2074         free(pattern_str);
 2075         return 0;
 2076     }
 2077 
 2078     uint32_t appId = lua_tointeger(L, index++);
 2079 
 2080     HTTPListElement *element = calloc(1, sizeof(*element));
 2081     if (element == NULL)
 2082     {
 2083         _dpd.errMsg( "Failed to allocate HTTP list element memory.");
 2084         free(pattern_str);
 2085         return 0;
 2086     }
 2087 
 2088     DetectorHTTPPattern *pattern = &element->detectorHTTPPattern;
 2089     tAppIdConfig *pConfig = detectorUserData->pDetector->pAppidNewConfig;
 2090 
 2091     pattern->seq           = seq;
 2092     pattern->service_id    = appGetAppFromServiceId(service_id, pConfig);
 2093     pattern->client_app    = appGetAppFromClientId(client_app, pConfig);
 2094     pattern->payload       = appGetAppFromPayloadId(payload, pConfig);
 2095     pattern->pattern       = pattern_str;
 2096     pattern->pattern_size  = (int) pattern_size;
 2097     pattern->appId         = appId;
 2098 
 2099     /* for apps that should not show up in 4.10 and ealier, we cannot include an entry in
 2100        the legacy client app or payload tables. We will use the appId instead. This is only for
 2101        user-agents that ID clients. if you want a user-agent to ID a payload, include it in the
 2102        payload database. If you want a host pattern ID, use the other API.  */
 2103 
 2104     if (!service_id && !client_app && !payload && pType == 2)
 2105     {
 2106         pattern->client_app = appId;
 2107     }
 2108 
 2109     switch(pType)
 2110     {
 2111         case HTTP_PAYLOAD:
 2112              element->next = pConfig->httpPatternLists.hostPayloadPatternList;
 2113              pConfig->httpPatternLists.hostPayloadPatternList = element;
 2114              break;
 2115 
 2116         case HTTP_URL:
 2117              element->next = pConfig->httpPatternLists.urlPatternList;
 2118              pConfig->httpPatternLists.urlPatternList = element;
 2119              break;
 2120 
 2121         case HTTP_USER_AGENT:
 2122              element->next = pConfig->httpPatternLists.clientAgentPatternList;
 2123              pConfig->httpPatternLists.clientAgentPatternList = element;
 2124              break;
 2125     }
 2126 
 2127     appInfoSetActive(pattern->service_id, true);
 2128     appInfoSetActive(pattern->client_app, true);
 2129     appInfoSetActive(pattern->payload, true);
 2130     appInfoSetActive(appId, true);
 2131 
 2132     return 0;
 2133 }
 2134 
 2135 /*  On the lua side, this should look something like:
 2136         addSSLCertPattern(<appId>, '<pattern string>' )
 2137 */
 2138 int Detector_addSSLCertPattern (lua_State *L)
 2139 {
 2140     uint8_t *pattern_str;
 2141     size_t pattern_size;
 2142     int index = 1;
 2143     uint8_t type;
 2144     tAppId app_id;
 2145 
 2146     DetectorUserData *detectorUserData = checkDetectorUserData(L, index++);
 2147     if (!detectorUserData || detectorUserData->pDetector->validateParams.pkt)
 2148     {
 2149         _dpd.errMsg( "Invalid SSL detector user data or context.");
 2150         return 0;
 2151     }
 2152 
 2153     type = lua_tointeger(L, index++);
 2154     app_id  = (tAppId) lua_tointeger(L, index++);
 2155 
 2156     pattern_size = 0;
 2157     const char *tmpString = lua_tolstring(L, index++, &pattern_size);
 2158     if (!tmpString || !pattern_size)
 2159     {
 2160         _dpd.errMsg( "Invalid SSL Host pattern string");
 2161         return 0;
 2162     }
 2163     pattern_str = (uint8_t *)strdup(tmpString);
 2164     if (!pattern_str)
 2165     {
 2166         _dpd.errMsg( "Invalid SSL Host pattern string.");
 2167         return 0;
 2168     }
 2169 
 2170     if (!ssl_add_cert_pattern(pattern_str, pattern_size, type, app_id, &detectorUserData->pDetector->pAppidNewConfig->serviceSslConfig))
 2171     {
 2172         free(pattern_str);
 2173         _dpd.errMsg( "Failed to add an SSL pattern list member");
 2174         return 0;
 2175     }
 2176 
 2177     appInfoSetActive(app_id, true);
 2178     return 0;
 2179 }
 2180 
 2181 /*  On the lua side, this should look something like:
 2182         addDNSHostPattern(<appId>, '<pattern string>' )
 2183 */
 2184 int Detector_addDNSHostPattern (lua_State *L)
 2185 {
 2186     uint8_t *pattern_str;
 2187     size_t pattern_size;
 2188     int index = 1;
 2189     uint8_t type;
 2190     tAppId app_id;
 2191 
 2192     DetectorUserData *detectorUserData = checkDetectorUserData(L, index++);
 2193     if (!detectorUserData || detectorUserData->pDetector->validateParams.pkt)
 2194     {
 2195         _dpd.errMsg( "LuaDetectorApi:Invalid DNS detector user data or context.");
 2196         return 0;
 2197     }
 2198 
 2199     type = lua_tointeger(L, index++);
 2200     app_id  = (tAppId) lua_tointeger(L, index++);
 2201 
 2202     pattern_size = 0;
 2203     const char *tmpString = lua_tolstring(L, index++, &pattern_size);
 2204     if (!tmpString || !pattern_size)
 2205     {
 2206         _dpd.errMsg( "LuaDetectorApi:Invalid DNS Host pattern string");
 2207         return 0;
 2208     }
 2209     pattern_str = (uint8_t *)strdup(tmpString);
 2210     if (!pattern_str)
 2211     {
 2212         _dpd.errMsg( "LuaDetectorApi:Invalid DNS Host pattern string.");
 2213         return 0;
 2214     }
 2215 
 2216     if (!dns_add_host_pattern(pattern_str, pattern_size, type, app_id, &detectorUserData->pDetector->pAppidNewConfig->serviceDnsConfig))
 2217     {
 2218         free(pattern_str);
 2219         _dpd.errMsg( "LuaDetectorApi:Failed to add an SSL pattern list member");
 2220     }
 2221 
 2222     return 0;
 2223 }
 2224 
 2225 static int Detector_addSSLCnamePattern (lua_State *L)
 2226 {
 2227     uint8_t *pattern_str;
 2228     size_t pattern_size;
 2229     int index = 1;
 2230     uint8_t type;
 2231     tAppId app_id;
 2232 
 2233     DetectorUserData *detectorUserData = checkDetectorUserData(L, index++);
 2234     if (!detectorUserData || detectorUserData->pDetector->validateParams.pkt)
 2235     {
 2236         _dpd.errMsg( "Invalid SSL detector user data or context.");
 2237         return 0;
 2238     }
 2239 
 2240     type = lua_tointeger(L, index++);
 2241     app_id  = (tAppId) lua_tointeger(L, index++);
 2242 
 2243 
 2244     pattern_size = 0;
 2245     const char *tmpString = lua_tolstring(L, index++, &pattern_size);
 2246     if (!tmpString || !pattern_size)
 2247     {
 2248         _dpd.errMsg( "Invalid SSL Host pattern string");
 2249         return 0;
 2250     }
 2251     pattern_str = (uint8_t *)strdup(tmpString);
 2252     if (!pattern_str)
 2253     {
 2254         _dpd.errMsg( "Invalid SSL Host pattern string.");
 2255         return 0;
 2256     }
 2257 
 2258     if (!ssl_add_cname_pattern(pattern_str, pattern_size, type, app_id, &detectorUserData->pDetector->pAppidNewConfig->serviceSslConfig))
 2259     {
 2260         free(pattern_str);
 2261         _dpd.errMsg( "Failed to add an SSL pattern list member");
 2262         return 0;
 2263     }
 2264 
 2265     appInfoSetActive(app_id, true);
 2266     return 0;
 2267 }
 2268 
 2269 static int Detector_addHostPortApp (lua_State *L)
 2270 {
 2271     /*uint8_t *ipaddr_str; */
 2272     size_t ipaddr_size;
 2273     int index = 1;
 2274     uint8_t type;
 2275     tAppId app_id;
 2276     struct in6_addr ip6Addr;
 2277 
 2278     DetectorUserData *detectorUserData = checkDetectorUserData(L, index++);
 2279     if (!detectorUserData || detectorUserData->pDetector->validateParams.pkt)
 2280     {
 2281         _dpd.errMsg("%s: Invalid detector user data or context.\n",__func__);
 2282         return 0;
 2283     }
 2284 
 2285     type = lua_tointeger(L, index++);
 2286     app_id  = (tAppId) lua_tointeger(L, index++);
 2287 
 2288     ipaddr_size = 0;
 2289     const char *tmpString = lua_tolstring(L, index++, &ipaddr_size);
 2290     if (!tmpString || !ipaddr_size)
 2291     {
 2292         _dpd.errMsg("%s:Invalid ipaddr string\n",__func__);
 2293         return 0;
 2294     }
 2295     if (!strchr(tmpString, ':'))
 2296     {
 2297         if (inet_pton(AF_INET, tmpString, &ip6Addr.s6_addr32[3]) <= 0)
 2298         {
 2299             _dpd.errMsg("%s: Invalid IP address: %s\n",__func__, tmpString);
 2300             return 0;
 2301         }
 2302         ip6Addr.s6_addr32[0] = ip6Addr.s6_addr32[1] =  0;
 2303         ip6Addr.s6_addr32[2] = ntohl(0x0000ffff);
 2304     }
 2305     else
 2306     {
 2307         if (inet_pton(AF_INET6, tmpString, &ip6Addr) <= 0)
 2308         {
 2309             _dpd.errMsg("%s: Invalid IP address: %s\n",__func__, tmpString);
 2310             return 0;
 2311         }
 2312     }
 2313     unsigned port  = lua_tointeger(L, index++);
 2314     unsigned proto  = lua_tointeger(L, index++);
 2315 
 2316     if (!hostPortAppCacheAdd(&ip6Addr, (uint16_t)port, (uint16_t)proto, type, app_id, detectorUserData->pDetector->pAppidNewConfig))
 2317     {
 2318         _dpd.errMsg("%s:Failed to backend call\n",__func__);
 2319     }
 2320 
 2321     return 0;
 2322 }
 2323 
 2324 static int Detector_addHostPortAppDynamic (lua_State *L)
 2325 {
 2326     /*uint8_t *ipaddr_str; */
 2327     size_t ipaddr_size;
 2328     int index = 1;
 2329     uint8_t type;
 2330     tAppId app_id;
 2331     struct in6_addr ip6Addr;
 2332 
 2333     DetectorUserData *detectorUserData = checkDetectorUserData(L, index++);
 2334     if (!detectorUserData)
 2335     {
 2336         _dpd.errMsg("%s: Invalid detector user data.\n",__func__);
 2337         return 0;
 2338     }
 2339 
 2340     type = lua_tointeger(L, index++);
 2341     app_id  = (tAppId) lua_tointeger(L, index++);
 2342 
 2343     ipaddr_size = 0;
 2344     const char *tmpString = lua_tolstring(L, index++, &ipaddr_size);
 2345     if (!tmpString || !ipaddr_size)
 2346     {
 2347         _dpd.errMsg("%s:Invalid ipaddr string\n",__func__);
 2348         return 0;
 2349     }
 2350     if (!strchr(tmpString, ':'))
 2351     {
 2352         if (inet_pton(AF_INET, tmpString, &ip6Addr.s6_addr32[3]) <= 0)
 2353         {
 2354             _dpd.errMsg("%s: Invalid IP address: %s\n",__func__, tmpString);
 2355             return 0;
 2356         }
 2357         ip6Addr.s6_addr32[0] = ip6Addr.s6_addr32[1] =  0;
 2358         ip6Addr.s6_addr32[2] = ntohl(0x0000ffff);
 2359     }
 2360     else
 2361     {
 2362         if (inet_pton(AF_INET6, tmpString, &ip6Addr) <= 0)
 2363         {
 2364             _dpd.errMsg("%s: Invalid IP address: %s\n",__func__, tmpString);
 2365             return 0;
 2366         }
 2367     }
 2368     unsigned port  = lua_tointeger(L, index++);
 2369     unsigned proto  = lua_tointeger(L, index++);
 2370 
 2371     if (!hostPortAppCacheDynamicAdd(&ip6Addr, (uint16_t)port, (uint16_t)proto, type, app_id, true))
 2372     {
 2373         _dpd.errMsg("%s:Failed to backend call\n",__func__);
 2374     }
 2375 
 2376     return 0;
 2377 }
 2378 
 2379 static int Detector_addContentTypePattern(lua_State *L)
 2380 {
 2381     uint8_t *pattern;
 2382     tAppId appId;
 2383     int index = 1;
 2384 
 2385     DetectorUserData *detectorUserData = checkDetectorUserData(L, index++);
 2386 
 2387     if (!detectorUserData)
 2388     {
 2389         _dpd.errMsg( "Invalid HTTP detector user data addContentTypePattern.");
 2390         return 0;
 2391     }
 2392 
 2393     size_t stringSize = 0;
 2394     const char *tmpString = lua_tolstring(L, index++, &stringSize);
 2395     if (!tmpString || !stringSize)
 2396     {
 2397         _dpd.errMsg( "Invalid HTTP Header string");
 2398         return 0;
 2399     }
 2400     pattern = (uint8_t *)strdup(tmpString);
 2401     if (!pattern)
 2402     {
 2403         _dpd.errMsg( "Failed to allocate Content Type pattern string.");
 2404         return 0;
 2405     }
 2406 
 2407     appId = lua_tointeger(L, index++);
 2408 
 2409     if (detectorUserData->pDetector->validateParams.pkt)
 2410     {
 2411         _dpd.errMsg("Invalid detector context addSipUserAgent: appId %d\n",appId);
 2412         free(pattern);
 2413         return 0;
 2414     }
 2415 
 2416     HTTPListElement *element = calloc(1, sizeof(*element));
 2417     if (!element)
 2418     {
 2419         _dpd.errMsg( "Failed to allocate HTTP list element memory.");
 2420         free(pattern);
 2421         return 0;
 2422     }
 2423 
 2424     DetectorHTTPPattern *detector = &element->detectorHTTPPattern;
 2425     tAppIdConfig        *pConfig  = detectorUserData->pDetector->pAppidNewConfig;
 2426 
 2427     detector->pattern = pattern;
 2428     detector->pattern_size = strlen((char *)pattern);
 2429     detector->appId = appId;
 2430 
 2431     element->next = pConfig->httpPatternLists.contentTypePatternList;
 2432     pConfig->httpPatternLists.contentTypePatternList = element;
 2433 
 2434     appInfoSetActive(appId, true);
 2435 
 2436     return 0;
 2437 }
 2438 
 2439 static inline int GetDetectorUserData(lua_State *L, int index,
 2440         DetectorUserData **detector_user_data, const char *errorString)
 2441 {
 2442     // Verify detector user data and that we are not in packet context
 2443     *detector_user_data = checkDetectorUserData(L, index);
 2444     if (!*detector_user_data || (*detector_user_data)->pDetector->validateParams.pkt)
 2445     {
 2446         _dpd.errMsg(errorString);
 2447         return -1;
 2448     }
 2449     return 0;
 2450 }
 2451 
 2452 static int detector_create_chp_app(DetectorUserData *detectorUserData, tAppId appIdInstance,
 2453                 unsigned app_type_flags, int num_matches)
 2454 {
 2455     CHPApp *new_app = (CHPApp *)calloc(1,sizeof(CHPApp));
 2456     if (!new_app)
 2457     {
 2458         _dpd.errMsg( "LuaDetectorApi:Failed to allocate CHP app memory.");
 2459         return -1;
 2460     }
 2461     new_app->appIdInstance = appIdInstance;
 2462     new_app->app_type_flags = app_type_flags;
 2463     new_app->num_matches = num_matches;
 2464 
 2465     if (sfxhash_add(detectorUserData->pDetector->pAppidNewConfig->CHP_glossary, &(new_app->appIdInstance), new_app))
 2466     {
 2467         _dpd.errMsg( "LuaDetectorApi:Failed to add CHP for appId %d, instance %d", CHP_APPIDINSTANCE_TO_ID(appIdInstance), CHP_APPIDINSTANCE_TO_INSTANCE(appIdInstance));
 2468         free(new_app);
 2469         return -1;
 2470     }
 2471     return 0;
 2472 }
 2473 
 2474 static int Detector_CHPCreateApp (lua_State *L)
 2475 {
 2476     DetectorUserData *detectorUserData;
 2477     tAppId appId;
 2478     unsigned app_type_flags;
 2479     int num_matches;
 2480 
 2481     tAppId appIdInstance;
 2482 
 2483     int index = 1;
 2484 
 2485     if (GetDetectorUserData(L, index++, &detectorUserData,
 2486         "LuaDetectorApi:Invalid HTTP detector user data in CHPCreateApp."))
 2487         return 0;
 2488 
 2489     appId = lua_tointeger(L, index++);
 2490     appIdInstance = CHP_APPID_SINGLE_INSTANCE(appId); // Last instance for the old API
 2491 
 2492     app_type_flags =    lua_tointeger(L, index++);
 2493     num_matches =       lua_tointeger(L, index++);
 2494 
 2495     // We only want one of these for each appId.
 2496     if (sfxhash_find(detectorUserData->pDetector->pAppidNewConfig->CHP_glossary, &appIdInstance))
 2497     {
 2498         _dpd.errMsg( "LuaDetectorApi:Attempt to add more than one CHP for appId %d - use CHPMultiCreateApp", appId);
 2499         return 0;
 2500     }
 2501 
 2502     detector_create_chp_app(detectorUserData, appIdInstance, app_type_flags, num_matches);
 2503     return 0;
 2504 }
 2505 
 2506 static inline int CHPGetKeyPatternBoolean(lua_State *L, int index)
 2507 {
 2508     return (0 != lua_tointeger(L, index));
 2509 }
 2510 
 2511 static inline int CHPGetPatternType(lua_State *L, int index, PatternType *pattern_type)
 2512 {
 2513     *pattern_type = (PatternType) lua_tointeger(L, index);
 2514     if(*pattern_type < AGENT_PT || *pattern_type > MAX_PATTERN_TYPE)
 2515     {
 2516         _dpd.errMsg( "LuaDetectorApi:Invalid CHP Action pattern type.");
 2517         return -1;
 2518     }
 2519     return 0;
 2520 }
 2521 
 2522 static inline int CHPGetPatternDataAndSize(lua_State *L, int index, char **pattern_data, size_t *pattern_size)
 2523 {
 2524     const char *tmpString = NULL; // Lua owns this pointer
 2525     *pattern_size = 0;
 2526     *pattern_data = NULL;
 2527     tmpString = lua_tolstring(L, index, &*pattern_size);
 2528     if(!tmpString || !*pattern_size || !(*pattern_data = strdup(tmpString))) // non-empty pattern required
 2529     {
 2530         if (*pattern_size) // implies strdup() failed
 2531             _dpd.errMsg( "LuaDetectorApi:CHP Action PATTERN string mem alloc failed.");
 2532         else
 2533             _dpd.errMsg( "LuaDetectorApi:Invalid CHP Action PATTERN string."); // empty string in Lua code - bad
 2534         return -1;
 2535     }
 2536     return 0;
 2537 }
 2538 
 2539 static inline int CHPGetActionType(lua_State *L, int index, ActionType *action_type)
 2540 {
 2541     *action_type = (ActionType) lua_tointeger(L, index);
 2542     if (*action_type < NO_ACTION || *action_type > MAX_ACTION_TYPE)
 2543     {
 2544         _dpd.errMsg( "LuaDetectorApi:Incompatible CHP Action type, might be for a later version.");
 2545         return -1;
 2546     }
 2547     return 0;
 2548 }
 2549 
 2550 static inline int CHPGetActionData(lua_State *L, int index, char **action_data)
 2551 {
 2552     // An empty string is translated into a NULL pointer because the action data is optional
 2553     const char *tmpString = NULL; // Lua owns this pointer
 2554     size_t action_data_size = 0;
 2555     *action_data = NULL;
 2556     tmpString = lua_tolstring(L, index, &action_data_size);
 2557     if (action_data_size)
 2558     {
 2559         if(!(*action_data = strdup(tmpString)))
 2560         {
 2561             _dpd.errMsg( "LuaDetectorApi:Action DATA string mem alloc failed.");
 2562             return -1;
 2563         }
 2564     }
 2565     return 0;
 2566 }
 2567 
 2568 static int detector_add_chp_action(DetectorUserData *detectorUserData,
 2569                     tAppId appIdInstance, int isKeyPattern, PatternType patternType,
 2570                     size_t patternSize, char *patternData, ActionType actionType, char *optionalActionData)
 2571 {
 2572     uint precedence;
 2573     CHPListElement *tmp_chpa, *prev_chpa, *chpa;
 2574     CHPApp *chpapp;
 2575     tAppIdConfig *pConfig = detectorUserData->pDetector->pAppidNewConfig;
 2576 
 2577     //find the CHP App for this
 2578     if (!(chpapp = sfxhash_find(detectorUserData->pDetector->pAppidNewConfig->CHP_glossary, &appIdInstance)))
 2579     {
 2580         _dpd.errMsg( "LuaDetectorApi:Invalid attempt to add a CHP action for unknown appId %d, instance %d. - pattern:\"%s\" - action \"%s\"\n",
 2581             CHP_APPIDINSTANCE_TO_ID(appIdInstance), CHP_APPIDINSTANCE_TO_INSTANCE(appIdInstance),
 2582             patternData, optionalActionData ? optionalActionData : "");
 2583         free(patternData);
 2584         if (optionalActionData) free(optionalActionData);
 2585         return 0;
 2586     }
 2587 
 2588     if (isKeyPattern)
 2589     {
 2590         chpapp->key_pattern_count++;
 2591         chpapp->key_pattern_length_sum += patternSize;
 2592     }
 2593 
 2594     if (chpapp->ptype_scan_counts[patternType] == 0)
 2595         chpapp->num_scans++;
 2596     precedence = chpapp->ptype_scan_counts[patternType]++; // The increment is for the sake of the precedence. ptype_scan_counts means "The scan DOES count toward the total required."
 2597     // at runtime we'll want to know how many of each type of pattern we are looking for.
 2598     if (actionType == REWRITE_FIELD || actionType == INSERT_FIELD)
 2599     {
 2600         if (!appInfoEntryFlagGet(CHP_APPIDINSTANCE_TO_ID(appIdInstance), APPINFO_FLAG_SUPPORTED_SEARCH, pConfig))
 2601         {
 2602             _dpd.errMsg( "LuaDetectorApi: CHP action type, %d, requires previous use of action type, %d, (see appId %d, pattern=\"%s\").\n",
 2603                 actionType, GET_OFFSETS_FROM_REBUILT, CHP_APPIDINSTANCE_TO_ID(appIdInstance), patternData);
 2604             free(patternData);
 2605             if (optionalActionData) free(optionalActionData);
 2606             return 0;
 2607         }
 2608         switch (patternType)
 2609         {
 2610             // permitted pattern type (modifiable HTTP/SPDY request field)
 2611             case AGENT_PT:
 2612             case HOST_PT:
 2613             case REFERER_PT:
 2614             case URI_PT:
 2615             case COOKIE_PT:
 2616                 break;
 2617             default:
 2618                 _dpd.errMsg( "LuaDetectorApi: CHP action type, %d, on unsupported pattern type, %d, (see appId %d, pattern=\"%s\").\n",
 2619                     actionType, patternType, CHP_APPIDINSTANCE_TO_ID(appIdInstance), patternData);
 2620                 free(patternData);
 2621                 if (optionalActionData) free(optionalActionData);
 2622                 return 0;
 2623         }
 2624     }
 2625     else if (actionType != ALTERNATE_APPID && actionType != DEFER_TO_SIMPLE_DETECT)
 2626         chpapp->ptype_req_counts[patternType]++;
 2627 
 2628     chpa = (CHPListElement*)calloc(1,sizeof(CHPListElement));
 2629     if (!chpa)
 2630     {
 2631         _dpd.errMsg( "LuaDetectorApi: Failed to allocate CHP action memory.\n");
 2632         free(patternData);
 2633         if (optionalActionData) free(optionalActionData);
 2634         return 0;
 2635     }
 2636     chpa->chp_action.appIdInstance = appIdInstance;
 2637     chpa->chp_action.precedence = precedence;
 2638     chpa->chp_action.key_pattern = isKeyPattern;
 2639     chpa->chp_action.ptype = patternType;
 2640     chpa->chp_action.psize = patternSize;
 2641     chpa->chp_action.pattern = patternData;
 2642     chpa->chp_action.action = actionType;
 2643     chpa->chp_action.action_data = optionalActionData;
 2644     chpa->chp_action.chpapp = chpapp; // link this struct to the Glossary entry
 2645 
 2646     tmp_chpa = pConfig->httpPatternLists.chpList;
 2647     if (!tmp_chpa) pConfig->httpPatternLists.chpList = chpa;
 2648     else
 2649     {
 2650         while (tmp_chpa->next)
 2651             tmp_chpa = tmp_chpa->next;
 2652         tmp_chpa->next = chpa;
 2653     }
 2654 
 2655     /* Set the safe-search bits in the appId entry */
 2656     if (actionType == GET_OFFSETS_FROM_REBUILT)
 2657     {
 2658         /* This is a search engine and it is SUPPORTED for safe-search packet rewrite */
 2659         appInfoEntryFlagSet(CHP_APPIDINSTANCE_TO_ID(appIdInstance), APPINFO_FLAG_SEARCH_ENGINE | APPINFO_FLAG_SUPPORTED_SEARCH, pConfig);
 2660     }
 2661     else if (actionType == SEARCH_UNSUPPORTED)
 2662     {
 2663         /* This is a search engine and it is UNSUPPORTED for safe-search packet rewrite */
 2664         appInfoEntryFlagSet(CHP_APPIDINSTANCE_TO_ID(appIdInstance), APPINFO_FLAG_SEARCH_ENGINE, pConfig);
 2665     }
 2666     else if (actionType == DEFER_TO_SIMPLE_DETECT && strcmp(patternData,"<ignore-all-patterns>") == 0)
 2667     {
 2668         // Walk the list of all the patterns we have inserted, searching for this appIdInstance and free them.
 2669         // The purpose is for the 14 and 15 to be used together to only set the APPINFO_FLAG_SEARCH_ENGINE flag
 2670         // If the reserved pattern is not used, it is a mixed use case and should just behave normally.
 2671         prev_chpa = NULL;
 2672         tmp_chpa = pConfig->httpPatternLists.chpList;
 2673         while (tmp_chpa)
 2674         {
 2675             if (tmp_chpa->chp_action.appIdInstance == appIdInstance)
 2676             {
 2677                 // advance the tmp_chpa pointer by removing the item pointed to. Keep prev_chpa unchanged.
 2678 
 2679                 // 1) unlink the struct, 2) free strings and then 3) free the struct.
 2680                 chpa = tmp_chpa; // preserve this pointer to be freed at the end.
 2681                 if (prev_chpa == NULL)
 2682                 {
 2683                     // Remove from head
 2684                     pConfig->httpPatternLists.chpList = tmp_chpa->next;
 2685                     tmp_chpa = pConfig->httpPatternLists.chpList;
 2686                 }
 2687                 else
 2688                 {
 2689                     // Remove from middle of list.
 2690                     prev_chpa->next = tmp_chpa->next;
 2691                     tmp_chpa = prev_chpa->next;
 2692                 }
 2693                 free(chpa->chp_action.pattern);
 2694                 if (chpa->chp_action.action_data) free(chpa->chp_action.action_data);
 2695                 free(chpa);
 2696             }
 2697             else
 2698             {
 2699                 // advance both pointers
 2700                 prev_chpa = tmp_chpa;
 2701                 tmp_chpa = tmp_chpa->next;
 2702             }
 2703         }
 2704     }
 2705     return 0;
 2706 }
 2707 static int Detector_CHPAddAction (lua_State *L)
 2708 {
 2709     DetectorUserData *detectorUserData;
 2710     int key_pattern;
 2711     PatternType ptype;
 2712     size_t psize;
 2713     char *pattern;
 2714     ActionType action;
 2715     char *action_data;
 2716 
 2717     tAppId appIdInstance;
 2718     tAppId appId;
 2719 
 2720     int index = 1;
 2721 
 2722     if (GetDetectorUserData(L, index++, &detectorUserData,
 2723         "LuaDetectorApi:Invalid HTTP detector user data in CHPAddAction."))
 2724         return 0;
 2725 
 2726     // Parameter 1
 2727     appId = lua_tointeger(L, index++);
 2728     appIdInstance = CHP_APPID_SINGLE_INSTANCE(appId); // Last instance for the old API
 2729 
 2730     // Parameter 2
 2731     key_pattern = CHPGetKeyPatternBoolean(L, index++);
 2732 
 2733     // Parameter 3
 2734     if (CHPGetPatternType(L, index++, &ptype))
 2735         return 0;
 2736 
 2737     // Parameter 4
 2738     if (CHPGetPatternDataAndSize(L, index++, &pattern, &psize))
 2739         return 0;
 2740 
 2741     // Parameter 5
 2742     if (CHPGetActionType(L, index++, &action))
 2743     {
 2744         free(pattern);
 2745         return 0;
 2746     }
 2747 
 2748     // Parameter 6
 2749     if (CHPGetActionData(L, index++, &action_data))
 2750     {
 2751         free(pattern);
 2752         return 0;
 2753     }
 2754 
 2755     return detector_add_chp_action(detectorUserData, appIdInstance, key_pattern, ptype,
 2756                     psize, pattern, action, action_data);
 2757 }
 2758 
 2759 static int Detector_CHPMultiCreateApp (lua_State *L)
 2760 {
 2761     DetectorUserData *detectorUserData;
 2762     tAppId appId;
 2763     unsigned app_type_flags;
 2764     int num_matches;
 2765 
 2766     tAppId appIdInstance;
 2767     int instance;
 2768 
 2769     int index = 1;
 2770 
 2771     if (GetDetectorUserData(L, index++, &detectorUserData,
 2772         "LuaDetectorApi:Invalid HTTP detector user data in CHPMultiCreateApp."))
 2773         return 0;
 2774 
 2775     appId =             lua_tointeger(L, index++);
 2776     app_type_flags =    lua_tointeger(L, index++);
 2777     num_matches =       lua_tointeger(L, index++);
 2778 
 2779     for (instance=0; instance < CHP_APPID_INSTANCE_MAX; instance++ )
 2780     {
 2781         appIdInstance = (appId << CHP_APPID_BITS_FOR_INSTANCE) + instance;
 2782         if (sfxhash_find(detectorUserData->pDetector->pAppidNewConfig->CHP_glossary, &appIdInstance))
 2783             continue;
 2784         break;
 2785     }
 2786 
 2787     // We only want a maximum of these for each appId.
 2788     if (instance == CHP_APPID_INSTANCE_MAX)
 2789     {
 2790         _dpd.errMsg( "LuaDetectorApi:Attempt to create more than %d CHP for appId %d", CHP_APPID_INSTANCE_MAX, appId);
 2791         return 0;
 2792     }
 2793 
 2794     if (detector_create_chp_app(detectorUserData, appIdInstance, app_type_flags, num_matches))
 2795         return 0;
 2796 
 2797     lua_pushnumber(L, appIdInstance);
 2798     return 1;
 2799 }
 2800 
 2801 
 2802 static int Detector_CHPMultiAddAction (lua_State *L)
 2803 {
 2804     DetectorUserData *detectorUserData;
 2805     int key_pattern;
 2806     PatternType ptype;
 2807     size_t psize;
 2808     char *pattern;
 2809     ActionType action;
 2810     char *action_data;
 2811 
 2812     tAppId appIdInstance;
 2813 
 2814     int index = 1;
 2815 
 2816     if (GetDetectorUserData(L, index++, &detectorUserData,
 2817         "LuaDetectorApi:Invalid HTTP detector user data in CHPMultiAddAction."))
 2818         return 0;
 2819 
 2820     // Parameter 1
 2821     appIdInstance = lua_tointeger(L, index++);
 2822 
 2823     // Parameter 2
 2824     key_pattern = CHPGetKeyPatternBoolean(L, index++);
 2825 
 2826     // Parameter 3
 2827     if (CHPGetPatternType(L, index++, &ptype))
 2828         return 0;
 2829 
 2830     // Parameter 4
 2831     if (CHPGetPatternDataAndSize(L, index++, &pattern, &psize))
 2832         return 0;
 2833 
 2834     // Parameter 5
 2835     if (CHPGetActionType(L, index++, &action))
 2836     {
 2837         free(pattern);
 2838         return 0;
 2839     }
 2840 
 2841     // Parameter 6
 2842     if (CHPGetActionData(L, index++, &action_data))
 2843     {
 2844         free(pattern);
 2845         return 0;
 2846     }
 2847 
 2848     return detector_add_chp_action(detectorUserData, appIdInstance, key_pattern, ptype,
 2849                     psize, pattern, action, action_data);
 2850 }
 2851 
 2852 static int Detector_portOnlyService (lua_State *L)
 2853 {
 2854     int index = 1;
 2855 
 2856     // Verify detector user data and that we are not in packet context
 2857     DetectorUserData *detectorUserData = checkDetectorUserData(L, index++);
 2858     if (!detectorUserData || detectorUserData->pDetector->validateParams.pkt)
 2859     {
 2860         _dpd.errMsg( "LuaDetectorApi:Invalid HTTP detector user data in addPortOnlyService.");
 2861         return 0;
 2862     }
 2863 
 2864     tAppId appId = lua_tointeger(L, index++);
 2865     u_int16_t port = lua_tointeger(L, index++);
 2866     u_int8_t protocol = lua_tointeger(L, index++);
 2867 
 2868     if (port == 0)
 2869         detectorUserData->pDetector->pAppidNewConfig->ip_protocol[protocol] = appId;
 2870     else if (protocol == 6)
 2871         detectorUserData->pDetector->pAppidNewConfig->tcp_port_only[port] = appId;
 2872     else if (protocol == 17)
 2873         detectorUserData->pDetector->pAppidNewConfig->udp_port_only[port] = appId;
 2874 
 2875     return 0;
 2876 }
 2877 
 2878 /* Add a length-based detector.  This is done by adding a new length sequence
 2879  * to the cache.  Note that this does not require a validate and is only used
 2880  * as a fallback identification.
 2881  *
 2882  * @param lua_State* - Lua state variable.
 2883  * @param appId/stack        - App ID to use for this detector.
 2884  * @param proto/stack        - Protocol (IPPROTO_TCP/DC.ipproto.tcp (6) or
 2885  *                             IPPROTO_UDP/DC.ipproto.udp (17)).
 2886  * @param sequence_cnt/stack - Number of elements in sequence below (max of
 2887  *                             LENGTH_SEQUENCE_CNT_MAX).
 2888  * @param sequence_str/stack - String that defines direction/length sequence.
 2889  *  - Example: "I/8,R/512,I/512,R/1024,I/1024"
 2890  *     - Direction: I(nitiator) or R(esponder).
 2891  *     - Length   : Payload size (bytes) (> 0).
 2892  * @return int - Number of elements on stack, which is always 1.
 2893  * @return status/stack - 0 if successful, -1 otherwise.
 2894  */
 2895 static int Detector_lengthAppCacheAdd(lua_State *L)
 2896 {
 2897     int         i;
 2898     const char *str_ptr;
 2899     uint16_t    length;
 2900     tLengthKey  length_sequence;
 2901     int         index = 1;
 2902 
 2903     DetectorUserData *detectorUserData = checkDetectorUserData(L, index++);
 2904     if (detectorUserData == NULL)
 2905     {
 2906         _dpd.errMsg( "LuaDetectorApi:Invalid detector user data!");
 2907         lua_pushnumber(L, -1);
 2908         return 1;
 2909     }
 2910 
 2911     tAppId      appId        = lua_tonumber(L, index++);
 2912     uint8_t     proto        = lua_tonumber(L, index++);
 2913     uint8_t     sequence_cnt = lua_tonumber(L, index++);
 2914     const char *sequence_str = lua_tostring(L, index++);
 2915 
 2916     if (((proto != IPPROTO_TCP) && (proto != IPPROTO_UDP))
 2917         || ((sequence_cnt == 0) || (sequence_cnt > LENGTH_SEQUENCE_CNT_MAX))
 2918         || ((sequence_str == NULL) || (strlen(sequence_str) == 0)))
 2919     {
 2920         _dpd.errMsg( "LuaDetectorApi:Invalid input (%d,%u,%u,\"%s\")!",
 2921                appId, (unsigned)proto, (unsigned)sequence_cnt, sequence_str ?: "");
 2922         lua_pushnumber(L, -1);
 2923         return 1;
 2924     }
 2925 
 2926     memset(&length_sequence, 0, sizeof(length_sequence));
 2927 
 2928     length_sequence.proto        = proto;
 2929     length_sequence.sequence_cnt = sequence_cnt;
 2930 
 2931     str_ptr = sequence_str;
 2932     for (i = 0; i < sequence_cnt; i++)
 2933     {
 2934         int last_one;
 2935 
 2936         switch (*str_ptr)
 2937         {
 2938         case 'I':
 2939             length_sequence.sequence[i].direction = APP_ID_FROM_INITIATOR;
 2940             break;
 2941         case 'R':
 2942             length_sequence.sequence[i].direction = APP_ID_FROM_RESPONDER;
 2943             break;
 2944         default:
 2945             _dpd.errMsg( "LuaDetectorApi:Invalid sequence string (\"%s\")!",
 2946                    sequence_str);
 2947             lua_pushnumber(L, -1);
 2948             return 1;
 2949         }
 2950         str_ptr++;
 2951 
 2952         if (*str_ptr != '/')
 2953         {
 2954             _dpd.errMsg( "LuaDetectorApi:Invalid sequence string (\"%s\")!",
 2955                    sequence_str);
 2956             lua_pushnumber(L, -1);
 2957             return 1;
 2958         }
 2959         str_ptr++;
 2960 
 2961         length = (uint16_t)atoi(str_ptr);
 2962         if (length == 0)
 2963         {
 2964             _dpd.errMsg( "LuaDetectorApi:Invalid sequence string (\"%s\")!",
 2965                    sequence_str);
 2966             lua_pushnumber(L, -1);
 2967             return 1;
 2968         }
 2969         length_sequence.sequence[i].length = length;
 2970 
 2971         while ((*str_ptr != ',') && (*str_ptr != 0))
 2972         {
 2973             str_ptr++;
 2974         }
 2975 
 2976         last_one = (i == (sequence_cnt - 1));
 2977         if (   (!last_one && (*str_ptr != ','))
 2978             || (last_one && (*str_ptr != 0)))
 2979         {
 2980             _dpd.errMsg( "LuaDetectorApi:Invalid sequence string (\"%s\")!",
 2981                    sequence_str);
 2982             lua_pushnumber(L, -1);
 2983             return 1;
 2984         }
 2985         str_ptr++;
 2986     }
 2987 
 2988     if (!lengthAppCacheAdd(&length_sequence, appId, detectorUserData->pDetector->pAppidNewConfig))
 2989     {
 2990         _dpd.errMsg( "LuaDetectorApi:Could not add entry to cache!");
 2991         lua_pushnumber(L, -1);
 2992         return 1;
 2993     }
 2994 
 2995     lua_pushnumber(L, 0);
 2996     return 1;
 2997 }
 2998 
 2999 static int Detector_AFAddApp (lua_State *L)
 3000 {
 3001     int index = 1;
 3002     AFElement val;
 3003 
 3004     DetectorUserData *detectorUserData = checkDetectorUserData(L, index++);
 3005     if (!detectorUserData || detectorUserData->pDetector->validateParams.pkt)
 3006     {
 3007         _dpd.errMsg( "LuaDetectorApi:Invalid HTTP detector user data in AFAddApp.");
 3008         return 0;
 3009     }
 3010 
 3011     tAppId indicator = lua_tointeger(L, index++);
 3012     tAppId forecast  = lua_tointeger(L, index++);
 3013     tAppId target    = lua_tointeger(L, index++);
 3014 
 3015     if (sfxhash_find(detectorUserData->pDetector->pAppidNewConfig->AF_indicators, &indicator))
 3016     {
 3017         _dpd.errMsg( "LuaDetectorApi:Attempt to add more than one AFElement per appId %d", indicator);
 3018         return 0;
 3019     }
 3020 
 3021     val.indicator = indicator;
 3022     val.forecast = forecast;
 3023     val.target = target;
 3024 
 3025     if (sfxhash_add(detectorUserData->pDetector->pAppidNewConfig->AF_indicators, &indicator, &val))
 3026     {
 3027         _dpd.errMsg( "LuaDetectorApi:Failed to add AFElement for appId %d", indicator);
 3028         return 0;
 3029     }
 3030 
 3031     return 0;
 3032 }
 3033 
 3034 static int Detector_addAppUrl(lua_State *L)
 3035 {
 3036     int index = 1;
 3037     DetectorAppUrlPattern **tmp;
 3038     const char *tmpString;
 3039 
 3040     /* Verify detector user data and that we are not in packet context */
 3041     DetectorUserData *detectorUserData = checkDetectorUserData(L, index++);
 3042     if (!detectorUserData || detectorUserData->pDetector->validateParams.pkt)
 3043     {
 3044         _dpd.errMsg( "Invalid HTTP detector user data in addAppUrl.");
 3045         return 0;
 3046     }
 3047 
 3048     u_int32_t service_id      = lua_tointeger(L, index++);
 3049     u_int32_t client_id      = lua_tointeger(L, index++);
 3050     lua_tointeger(L, index++); // client_app_type
 3051     u_int32_t payload_id         = lua_tointeger(L, index++);
 3052     lua_tointeger(L, index++); // payload_type
 3053 
 3054     if (detectorUserData->pDetector->validateParams.pkt)
 3055     {
 3056         _dpd.errMsg("Invalid HTTP detector context addAppUrl: service_id %u; client_id %u; payload_id %u\n",service_id, client_id, payload_id);
 3057         return 0;
 3058     }
 3059 
 3060     /* Verify that host pattern is a valid string */
 3061     size_t hostPatternSize = 0;
 3062     u_int8_t* hostPattern = NULL;
 3063     tmpString = lua_tolstring(L, index++, &hostPatternSize);
 3064     if(!tmpString || !hostPatternSize)
 3065     {
 3066         _dpd.errMsg( "Invalid host pattern string:service_id %u; client_id %u; payload_id %u\n.",service_id, client_id, payload_id);
 3067         return 0;
 3068     }
 3069     else if (!(hostPattern = (u_int8_t *)strdup(tmpString)))
 3070     {
 3071         _dpd.errMsg( "Failed to duplicate host pattern: %s, service_id %u; client_id %u; payload_id %u\n.",tmpString, service_id, client_id, payload_id);
 3072         return 0;
 3073     }
 3074 
 3075     /* Verify that path pattern is a valid string */
 3076     size_t pathPatternSize = 0;
 3077     u_int8_t* pathPattern = NULL;
 3078     tmpString = lua_tolstring(L, index++, &pathPatternSize);
 3079     if(!tmpString || !pathPatternSize)
 3080     {
 3081         _dpd.errMsg( "Invalid path pattern string: service_id %u; client_id %u; payload_id %u\n.",service_id, client_id, payload_id);
 3082         free(hostPattern);
 3083         return 0;
 3084     }
 3085     else if (!(pathPattern = (u_int8_t *)strdup(tmpString)))
 3086     {
 3087         _dpd.errMsg( "Failed to duplicate path pattern: %s, service_id %u; client_id %u; payload_id %u\n.",tmpString, service_id, client_id, payload_id);
 3088         free(hostPattern);
 3089         return 0;
 3090     }
 3091 
 3092     /* Verify that scheme pattern is a valid string */
 3093     size_t schemePatternSize;
 3094     u_int8_t* schemePattern = NULL;
 3095     tmpString = lua_tolstring(L, index++, &schemePatternSize);
 3096     if(!tmpString || !schemePatternSize)
 3097     {
 3098         _dpd.errMsg( "Invalid scheme pattern string: service_id %u; client_id %u; payload_id %u\n.",service_id, client_id, payload_id);
 3099         free(pathPattern);
 3100         free(hostPattern);
 3101         return 0;
 3102     }
 3103     else if (!(schemePattern = (u_int8_t*) strdup(tmpString)))
 3104     {
 3105         _dpd.errMsg( "Failed to duplicate scheme pattern: %s, service_id %u; client_id %u; payload_id %u\n.",tmpString, service_id, client_id, payload_id);
 3106         free(pathPattern);
 3107         free(hostPattern);
 3108         return 0;
 3109     }
 3110 
 3111     /* Verify that query pattern is a valid string */
 3112     size_t queryPatternSize;
 3113     u_int8_t* queryPattern = NULL;
 3114     tmpString = lua_tolstring(L, index++, &queryPatternSize);
 3115     if(tmpString  && queryPatternSize)
 3116     {
 3117         if (!(queryPattern = (u_int8_t*) strdup(tmpString)))
 3118         {
 3119             _dpd.errMsg( "Invalid query pattern string.");
 3120             free(hostPattern);
 3121             free(pathPattern);
 3122             free(schemePattern);
 3123             return 0;
 3124         }
 3125     }
 3126 
 3127     u_int32_t appId           = lua_tointeger(L, index++);
 3128 
 3129     /* Allocate memory for data structures */
 3130     DetectorAppUrlPattern *pattern = malloc(sizeof(DetectorAppUrlPattern));
 3131     if (!pattern)
 3132     {
 3133         _dpd.errMsg( "Failed to allocate HTTP pattern memory.");
 3134         free(hostPattern);
 3135         free(pathPattern);
 3136         free(schemePattern);
 3137         if (queryPattern) free(queryPattern);
 3138         return 0;
 3139     }
 3140 
 3141     tAppIdConfig       *pConfig = detectorUserData->pDetector->pAppidNewConfig;
 3142 
 3143     pattern->userData.service_id        = appGetAppFromServiceId(service_id, pConfig);
 3144     pattern->userData.client_app        = appGetAppFromClientId(client_id, pConfig);
 3145     pattern->userData.payload           = appGetAppFromPayloadId(payload_id, pConfig);
 3146     pattern->userData.appId             = appId;
 3147     pattern->userData.query.pattern     = queryPattern;
 3148     pattern->userData.query.patternSize = queryPatternSize;
 3149     pattern->patterns.host.pattern              = hostPattern;
 3150     pattern->patterns.host.patternSize         = (int) hostPatternSize;
 3151     pattern->patterns.path.pattern              = pathPattern;
 3152     pattern->patterns.path.patternSize         = (int) pathPatternSize;
 3153     pattern->patterns.scheme.pattern              = schemePattern;
 3154     pattern->patterns.scheme.patternSize         = (int) schemePatternSize;
 3155 
 3156     DetectorAppUrlList *urlList = &pConfig->httpPatternLists.appUrlList;
 3157 
 3158     /**first time usedCount and allocatedCount are both 0, urlPattern will be NULL.
 3159      * This case is same as malloc. In case of error, realloc will return NULL, and
 3160      * original urlPattern buffer is left untouched.
 3161      */
 3162     if (urlList->usedCount == urlList->allocatedCount)
 3163     {
 3164         tmp = realloc(urlList->urlPattern, (urlList->allocatedCount+URL_LIST_STEP_SIZE)*sizeof(*tmp));
 3165         if (!tmp)
 3166         {
 3167             FreeDetectorAppUrlPattern(pattern);
 3168             return 0;
 3169         }
 3170         urlList->urlPattern = tmp;
 3171         urlList->allocatedCount += URL_LIST_STEP_SIZE;
 3172     }
 3173 
 3174     urlList->urlPattern[urlList->usedCount++] = pattern;
 3175 
 3176     appInfoSetActive(pattern->userData.service_id, true);
 3177     appInfoSetActive(pattern->userData.client_app, true);
 3178     appInfoSetActive(pattern->userData.payload, true);
 3179     appInfoSetActive(appId, true);
 3180 
 3181     return 0;
 3182 }
 3183 
 3184 static int Detector_addRTMPUrl(lua_State *L)
 3185 {
 3186     int index = 1;
 3187     DetectorAppUrlPattern **tmp;
 3188     const char *tmpString;
 3189 
 3190     /* Verify detector user data and that we are not in packet context */
 3191     DetectorUserData *detectorUserData = checkDetectorUserData(L, index++);
 3192     if (!detectorUserData || detectorUserData->pDetector->validateParams.pkt)
 3193     {
 3194         _dpd.errMsg( "Invalid HTTP detector user data in addRTMPUrl.");
 3195         return 0;
 3196     }
 3197 
 3198     u_int32_t service_id      = lua_tointeger(L, index++);
 3199     u_int32_t client_id      = lua_tointeger(L, index++);
 3200     lua_tointeger(L, index++); // client_app_type 
 3201     u_int32_t payload_id         = lua_tointeger(L, index++);
 3202     lua_tointeger(L, index++); // payload_type
 3203 
 3204     if (detectorUserData->pDetector->validateParams.pkt)
 3205     {
 3206         _dpd.errMsg("Invalid HTTP detector context addRTMPUrl: service_id %u; client_id %u; payload_id %u\n",service_id, client_id, payload_id);
 3207         return 0;
 3208     }
 3209 
 3210     /* Verify that host pattern is a valid string */
 3211     size_t hostPatternSize = 0;
 3212     u_int8_t* hostPattern = NULL;
 3213     tmpString = lua_tolstring(L, index++, &hostPatternSize);
 3214     if(!tmpString || !hostPatternSize) 
 3215     {
 3216         _dpd.errMsg( "Invalid host pattern string:service_id %u; client_id %u; payload_id %u\n",service_id, client_id, payload_id);
 3217         return 0;
 3218     }
 3219     else if (!(hostPattern = (u_int8_t *)strdup(tmpString)))
 3220     {
 3221         _dpd.errMsg( "Failed to duplicate host pattern: %s, service_id %u; client_id %u; payload_id %u\n.",tmpString, service_id, client_id, payload_id);
 3222         return 0;
 3223     }
 3224 
 3225     /* Verify that path pattern is a valid string */
 3226     size_t pathPatternSize = 0;
 3227     u_int8_t* pathPattern = NULL;
 3228     tmpString = lua_tolstring(L, index++, &pathPatternSize);
 3229     if(!tmpString || !pathPatternSize)
 3230     {
 3231         _dpd.errMsg( "Invalid path pattern string: service_id %u; client_id %u; payload_id %u\n.",service_id, client_id, payload_id);
 3232         free(hostPattern);
 3233         return 0;
 3234     }
 3235     else if (!(pathPattern = (u_int8_t *)strdup(tmpString)))
 3236     {
 3237         _dpd.errMsg( "Failed to duplicate path pattern: %s, service_id %u; client_id %u; payload_id %u\n.",tmpString, service_id, client_id, payload_id);
 3238         free(hostPattern);
 3239         return 0;
 3240     }
 3241 
 3242     /* Verify that scheme pattern is a valid string */
 3243     size_t schemePatternSize;
 3244     u_int8_t* schemePattern = NULL;
 3245     tmpString = lua_tolstring(L, index++, &schemePatternSize);
 3246     if(!tmpString || !schemePatternSize) 
 3247     {
 3248         _dpd.errMsg( "Invalid scheme pattern string: service_id %u; client_id %u; payload_id %u\n",service_id, client_id, payload_id);
 3249         free(pathPattern);
 3250         free(hostPattern);
 3251         return 0;
 3252     }
 3253     else if (!(schemePattern = (u_int8_t*) strdup(tmpString)))
 3254     {
 3255         _dpd.errMsg( "Failed to duplicate scheme pattern: %s, service_id %u; client_id %u; payload_id %u\n.",tmpString, service_id, client_id, payload_id);
 3256         free(pathPattern);
 3257         free(hostPattern);
 3258         return 0;
 3259     }
 3260 
 3261     /* Verify that query pattern is a valid string */
 3262     size_t queryPatternSize;
 3263     u_int8_t* queryPattern = NULL;
 3264     tmpString = lua_tolstring(L, index++, &queryPatternSize);
 3265     if(tmpString  && queryPatternSize)
 3266     {
 3267         if (!(queryPattern = (u_int8_t*) strdup(tmpString)))
 3268         {
 3269             _dpd.errMsg( "Invalid query pattern string.");
 3270             free(hostPattern);
 3271             free(pathPattern);
 3272             free(schemePattern);
 3273             return 0;
 3274         }
 3275     }
 3276 
 3277     u_int32_t appId           = lua_tointeger(L, index++);
 3278 
 3279     /* Allocate memory for data structures */
 3280     DetectorAppUrlPattern *pattern = malloc(sizeof(DetectorAppUrlPattern));
 3281     if (!pattern)
 3282     {
 3283         _dpd.errMsg( "Failed to allocate HTTP pattern memory.");
 3284         free(hostPattern);
 3285         free(pathPattern);
 3286         free(schemePattern);
 3287         if (queryPattern) free(queryPattern);
 3288         return 0;
 3289     }
 3290 
 3291     /* we want to put these patterns in just like for regular Urls, but we do NOT need legacy IDs for them.
 3292      * so just use the appID for service, client, or payload ID */
 3293     pattern->userData.service_id        = service_id;
 3294     pattern->userData.client_app        = client_id;
 3295     pattern->userData.payload           = payload_id;
 3296     pattern->userData.appId             = appId;
 3297     pattern->userData.query.pattern     = queryPattern;
 3298     pattern->userData.query.patternSize = queryPatternSize;
 3299     pattern->patterns.host.pattern              = hostPattern;
 3300     pattern->patterns.host.patternSize         = (int) hostPatternSize;
 3301     pattern->patterns.path.pattern              = pathPattern;
 3302     pattern->patterns.path.patternSize         = (int) pathPatternSize;
 3303     pattern->patterns.scheme.pattern              = schemePattern;
 3304     pattern->patterns.scheme.patternSize         = (int) schemePatternSize;
 3305 
 3306     tAppIdConfig       *pConfig = detectorUserData->pDetector->pAppidNewConfig;
 3307     DetectorAppUrlList *urlList = &pConfig->httpPatternLists.RTMPUrlList;
 3308 
 3309     /**first time usedCount and allocatedCount are both 0, urlPattern will be NULL.
 3310      * This case is same as malloc. In case of error, realloc will return NULL, and
 3311      * original urlPattern buffer is left untouched.
 3312      */
 3313     if (urlList->usedCount == urlList->allocatedCount)
 3314     {
 3315         tmp = realloc(urlList->urlPattern, (urlList->allocatedCount+URL_LIST_STEP_SIZE)*sizeof(*tmp));
 3316         if (!tmp)
 3317         {
 3318             FreeDetectorAppUrlPattern(pattern);
 3319             return 0;
 3320         }
 3321         urlList->urlPattern = tmp;
 3322         urlList->allocatedCount += URL_LIST_STEP_SIZE;
 3323     }
 3324 
 3325     urlList->urlPattern[urlList->usedCount++] = pattern;
 3326 
 3327     appInfoSetActive(pattern->userData.service_id, true);
 3328     appInfoSetActive(pattern->userData.client_app, true);
 3329     appInfoSetActive(pattern->userData.payload, true);
 3330     appInfoSetActive(appId, true);
 3331 
 3332     return 0;
 3333 }
 3334 
 3335 /*Lua should inject patterns in <clientAppId, clientVersion, multi-Pattern> format. */
 3336 static int Detector_addSipUserAgent(lua_State *L)
 3337 {
 3338     int index = 1;
 3339 
 3340     /* Verify detector user data and that we are not in packet context */
 3341     DetectorUserData *detectorUserData = checkDetectorUserData(L, index++);
 3342     if (!detectorUserData)
 3343     {
 3344         _dpd.errMsg( "Invalid HTTP detector user data addSipUserAgent.");
 3345         return 0;
 3346     }
 3347 
 3348     u_int32_t client_app      = lua_tointeger(L, index++);
 3349     const char *clientVersion       = lua_tostring(L, index++);
 3350     if(!clientVersion )
 3351     {
 3352         _dpd.errMsg( "Invalid sip client version string.");
 3353         return 0;
 3354     }
 3355 
 3356     if (detectorUserData->pDetector->validateParams.pkt)
 3357     {
 3358         _dpd.errMsg("Invalid detector context addSipUserAgent: client_app %u\n",client_app);
 3359         return 0;
 3360     }
 3361 
 3362     /* Verify that ua pattern is a valid string */
 3363     const char* uaPattern = lua_tostring(L, index++);
 3364     if(!uaPattern)
 3365     {
 3366         _dpd.errMsg( "Invalid sip ua pattern string.");
 3367         return 0;
 3368     }
 3369 
 3370     sipUaPatternAdd(client_app, clientVersion, uaPattern, &detectorUserData->pDetector->pAppidNewConfig->detectorSipConfig);
 3371 
 3372     appInfoSetActive(client_app, true);
 3373 
 3374     return 0;
 3375 }
 3376 
 3377 static int openCreateApp(lua_State *L)
 3378 {
 3379     int index = 1;
 3380     const char *tmpString;
 3381 
 3382     /* Verify detector user data and that we are not in packet context */
 3383     DetectorUserData *detectorUserData = checkDetectorUserData(L, index++);
 3384     if (!detectorUserData || detectorUserData->pDetector->validateParams.pkt)
 3385     {
 3386         _dpd.errMsg( "Invalid HTTP detector user data in addAppUrl.");
 3387         return 0;
 3388     }
 3389 
 3390     /* Verify that host pattern is a valid string */
 3391     size_t appNameLen = 0;
 3392     tmpString = lua_tolstring(L, index++, &appNameLen);
 3393     if(!tmpString || !appNameLen)
 3394     {
 3395         _dpd.errMsg( "Invalid appName string.");
 3396         lua_pushnumber(L, APP_ID_NONE);
 3397         return 1;   /*number of results */
 3398     }
 3399 
 3400     AppInfoTableEntry *entry = appInfoEntryCreate(tmpString, detectorUserData->pDetector->pAppidNewConfig);
 3401 
 3402     if (entry)
 3403     {
 3404         lua_pushnumber(L, entry->appId);
 3405         return 1;   /*number of results */
 3406     }
 3407 
 3408     lua_pushnumber(L, APP_ID_NONE);
 3409     return 1;   /*number of results */
 3410 }
 3411 
 3412 static int openAddClientApp(
 3413         lua_State *L
 3414         )
 3415 {
 3416     unsigned int serviceAppId, clientAppId;
 3417     Detector *detector;
 3418     DetectorUserData *detectorUserData = checkDetectorUserData(L, 1);
 3419 
 3420     serviceAppId = lua_tonumber(L, 2);
 3421     clientAppId = lua_tonumber(L, 3);
 3422 
 3423     /*check inputs and whether this function is called in context of a */
 3424     /*packet */
 3425     if (!detectorUserData || !detectorUserData->pDetector->validateParams.pkt)
 3426     {
 3427         lua_pushnumber(L, -1);
 3428         return 1;
 3429     }
 3430 
 3431     detector = detectorUserData->pDetector;
 3432 
 3433     if (!detector->client.appModule.api)
 3434     {
 3435         lua_pushnumber(L, -1);
 3436         return 1;
 3437     }
 3438 
 3439     detector->client.appModule.api->add_app(detector->validateParams.pkt, (APPID_SESSION_DIRECTION) detector->validateParams.dir, detector->pAppidActiveConfig, detector->validateParams.flowp, serviceAppId, clientAppId, "");
 3440 
 3441     lua_pushnumber(L, 0);
 3442     return 1;
 3443 }
 3444 
 3445 /** Add service id to a flow. Positive identification by a detector.
 3446  *
 3447  * @param Lua_State* - Lua state variable.
 3448  * @param detector/stack - detector object
 3449  * @param serviceId/stack - id of service postively identified on this flow.
 3450  * @param vendorName/stack - name of vendor of service. This is optional.
 3451  * @param version/stack - version of service. This is optional.
 3452  * @return int - Number of elements on stack, which is always 1.
 3453  * @return int/stack - values from enum SERVICE_RETCODE
 3454  */
 3455 static int openAddServiceApp(
 3456         lua_State *L
 3457         )
 3458 {
 3459     unsigned int serviceId, retValue = SERVICE_ENULL;
 3460     Detector *detector;
 3461     DetectorUserData *detectorUserData = checkDetectorUserData(L, 1);
 3462 
 3463     serviceId = lua_tonumber(L, 2);
 3464 
 3465     if (!detectorUserData || !checkServiceElement(detectorUserData->pDetector)
 3466            || !detectorUserData->pDetector->validateParams.pkt)
 3467     {
 3468         lua_pushnumber(L, SERVICE_ENULL);
 3469         return 1;
 3470     }
 3471 
 3472     detector = detectorUserData->pDetector;
 3473 
 3474     /*Phase2 - discuss RNAServiceSubtype will be maintained on lua side therefore the last parameter on the following call is NULL. */
 3475     /*Subtype is not displayed on DC at present. */
 3476     retValue = AppIdServiceAddService(detector->validateParams.flowp, detector->validateParams.pkt,
 3477             detector->validateParams.dir, detector->server.pServiceElement,
 3478             serviceId, NULL, NULL, NULL, NULL);
 3479 
 3480     lua_pushnumber(L, retValue);
 3481     return 1;
 3482 }
 3483 
 3484 static int openAddPayloadApp(
 3485         lua_State *L
 3486         )
 3487 {
 3488     unsigned int payloadAppId;
 3489     Detector *detector;
 3490     DetectorUserData *detectorUserData = checkDetectorUserData(L, 1);
 3491 
 3492     payloadAppId = lua_tonumber(L, 2);
 3493 
 3494     /*check inputs and whether this function is called in context of a */
 3495     /*packet */
 3496     if (!detectorUserData || !detectorUserData->pDetector->validateParams.pkt)
 3497     {
 3498         lua_pushnumber(L, -1);
 3499         return 1;
 3500     }
 3501 
 3502     detector = detectorUserData->pDetector;
 3503 
 3504     if (!detector->client.appModule.api)
 3505     {
 3506         lua_pushnumber(L, -1);
 3507         return 1;
 3508     }
 3509 
 3510     detector->client.appModule.api->add_payload(detector->validateParams.flowp, payloadAppId);
 3511 
 3512     lua_pushnumber(L, 0);
 3513     return 1;
 3514 }
 3515 
 3516 int openAddHttpPattern(lua_State *L)
 3517 {
 3518     int index = 1;
 3519     tAppIdConfig *pConfig;
 3520 
 3521     /* Verify detector user data and that we are not in packet context */
 3522     DetectorUserData *detectorUserData = checkDetectorUserData(L, index++);
 3523     if (!detectorUserData)
 3524     {
 3525         _dpd.errMsg( "Invalid HTTP detector user data addHttpPattern.");
 3526         return 0;
 3527     }
 3528 
 3529     pConfig = detectorUserData->pDetector->pAppidNewConfig;
 3530 
 3531     /* Verify valid pattern type */
 3532     enum httpPatternType pType = (enum httpPatternType) lua_tointeger(L, index++);
 3533     if(pType < HTTP_PAYLOAD || pType > HTTP_URL)
 3534     {
 3535         _dpd.errMsg( "Invalid HTTP pattern type.");
 3536         return 0;
 3537     }
 3538 
 3539     /* Verify valid DHSequence */
 3540     DHPSequence seq  = (DHPSequence) lua_tointeger(L, index++);
 3541     if(seq < SINGLE || seq > USER_AGENT_HEADER)
 3542     {
 3543         _dpd.errMsg( "Invalid HTTP DHP Sequence.");
 3544         return 0;
 3545     }
 3546 
 3547     uint32_t serviceAppId  = lua_tointeger(L, index++);
 3548     uint32_t clientAppId   = lua_tointeger(L, index++);
 3549     uint32_t payloadAppId  = lua_tointeger(L, index++);
 3550 
 3551     if (detectorUserData->pDetector->validateParams.pkt)
 3552     {
 3553         _dpd.errMsg("Invalid detector context addHttpPattern: serviceAppId %u; clientAppId %u; payloadAppId %u\n",serviceAppId, clientAppId, payloadAppId);
 3554         return 0;
 3555     }
 3556 
 3557     /* Verify that pattern is a valid string */
 3558     size_t pattern_size = 0;
 3559     uint8_t* pattern_str = (uint8_t*) strdup(lua_tolstring(L, index++, &pattern_size));
 3560     if(pattern_str == NULL || pattern_size == 0)
 3561     {
 3562         _dpd.errMsg( "Invalid HTTP pattern string.");
 3563         free(pattern_str);
 3564         return 0;
 3565     }
 3566 
 3567     HTTPListElement *element = calloc(1, sizeof(*element));
 3568     if (element == NULL)
 3569     {
 3570         _dpd.errMsg( "Failed to allocate HTTP list element memory.");
 3571         free(pattern_str);
 3572         return 0;
 3573     }
 3574 
 3575     DetectorHTTPPattern *pattern = &element->detectorHTTPPattern;
 3576     pattern->seq           = seq;
 3577     pattern->service_id    = serviceAppId;
 3578     pattern->client_app    = clientAppId;
 3579     pattern->payload       = payloadAppId;
 3580     pattern->pattern       = pattern_str;
 3581     pattern->pattern_size  = (int) pattern_size;
 3582     pattern->appId         = APP_ID_NONE;
 3583 
 3584     switch(pType)
 3585     {
 3586         case HTTP_PAYLOAD:
 3587              element->next = pConfig->httpPatternLists.hostPayloadPatternList;
 3588              pConfig->httpPatternLists.hostPayloadPatternList = element;
 3589              break;
 3590 
 3591         case HTTP_URL:
 3592              element->next = pConfig->httpPatternLists.urlPatternList;
 3593              pConfig->httpPatternLists.urlPatternList = element;
 3594              break;
 3595 
 3596         case HTTP_USER_AGENT:
 3597              element->next = pConfig->httpPatternLists.clientAgentPatternList;
 3598              pConfig->httpPatternLists.clientAgentPatternList = element;
 3599              break;
 3600     }
 3601 
 3602     appInfoSetActive(serviceAppId, true);
 3603     appInfoSetActive(clientAppId, true);
 3604     appInfoSetActive(payloadAppId, true);
 3605 
 3606     return 0;
 3607 }
 3608 
 3609 static int openAddUrlPattern(lua_State *L)
 3610 {
 3611     int index = 1;
 3612     DetectorAppUrlPattern **tmp;
 3613     const char *tmpString;
 3614 
 3615     /* Verify detector user data and that we are not in packet context */
 3616     DetectorUserData *detectorUserData = checkDetectorUserData(L, index++);
 3617     if (!detectorUserData || detectorUserData->pDetector->validateParams.pkt)
 3618     {
 3619         _dpd.errMsg( "Invalid HTTP detector user data in addAppUrl.");
 3620         return 0;
 3621     }
 3622 
 3623     tAppIdConfig *pConfig = detectorUserData->pDetector->pAppidNewConfig;
 3624     u_int32_t service_id    = lua_tointeger(L, index++);
 3625     u_int32_t client_id         = lua_tointeger(L, index++);
 3626     u_int32_t payload_id        = lua_tointeger(L, index++);
 3627 
 3628     if (detectorUserData->pDetector->validateParams.pkt)
 3629     {
 3630         _dpd.errMsg("Invalid HTTP detector context addAppUrl: service_id %u; client_id %u; payload_id %u\n",service_id, client_id, payload_id);
 3631         return 0;
 3632     }
 3633 
 3634     /* Verify that host pattern is a valid string */
 3635     size_t hostPatternSize = 0;
 3636     u_int8_t* hostPattern = NULL;
 3637     tmpString = lua_tolstring(L, index++, &hostPatternSize);
 3638     if(!tmpString || !hostPatternSize)
 3639     {
 3640         _dpd.errMsg( "Invalid host pattern string: service_id %u; client_id %u; payload_id %u\n",service_id, client_id, payload_id);
 3641         return 0;
 3642     }
 3643     else if (!(hostPattern = (u_int8_t *)strdup(tmpString)))
 3644     {
 3645         _dpd.errMsg( "Failed to duplicate host pattern: %s, service_id %u; client_id %u; payload_id %u\n.",tmpString, service_id, client_id, payload_id);
 3646         return 0;
 3647     }
 3648 
 3649     /* Verify that path pattern is a valid string */
 3650     size_t pathPatternSize = 0;
 3651     u_int8_t* pathPattern = NULL;
 3652     tmpString = lua_tolstring(L, index++, &pathPatternSize);
 3653     if(!tmpString || !pathPatternSize)
 3654     {
 3655         _dpd.errMsg( "Invalid path pattern string: service_id %u; client_id %u; payload %u\n.",service_id, client_id, payload_id);
 3656         free(hostPattern);
 3657         return 0;
 3658     }
 3659     else if (!(pathPattern = (u_int8_t *)strdup(tmpString)))
 3660     {
 3661         _dpd.errMsg( "Failed to duplicate path pattern: %s, service_id %u; client_id %u; payload %u\n.",tmpString, service_id, client_id, payload_id);
 3662         free(hostPattern);
 3663         return 0;
 3664     }
 3665 
 3666     /* Verify that scheme pattern is a valid string */
 3667     size_t schemePatternSize;
 3668     u_int8_t* schemePattern = NULL;
 3669     tmpString = lua_tolstring(L, index++, &schemePatternSize);
 3670     if(!tmpString || !schemePatternSize) 
 3671     {
 3672         _dpd.errMsg( "Invalid scheme pattern string: service_id %u; client_id %u; payload_id %u\n",service_id, client_id, payload_id);
 3673         free(pathPattern);
 3674         free(hostPattern);
 3675         return 0;
 3676     }
 3677     else if (!(schemePattern = (u_int8_t*) strdup(tmpString)))
 3678     {
 3679         _dpd.errMsg( "Failed to duplicate scheme pattern: %s, service_id %u; client_id %u; payload_id %u\n.",tmpString, service_id, client_id, payload_id);
 3680         free(pathPattern);
 3681         free(hostPattern);
 3682         return 0;
 3683     }
 3684 
 3685     /* Allocate memory for data structures */
 3686     DetectorAppUrlPattern *pattern = malloc(sizeof(DetectorAppUrlPattern));
 3687     if (!pattern)
 3688     {
 3689         _dpd.errMsg( "Failed to allocate HTTP pattern memory.");
 3690         free(hostPattern);
 3691         free(pathPattern);
 3692         free(schemePattern);
 3693         return 0;
 3694     }
 3695 
 3696 
 3697     pattern->userData.service_id        = service_id;
 3698     pattern->userData.client_app        = client_id;
 3699     pattern->userData.payload           = payload_id;
 3700     pattern->userData.appId             = APP_ID_NONE;
 3701     pattern->userData.query.pattern     = NULL;
 3702     pattern->userData.query.patternSize = 0;
 3703     pattern->patterns.host.pattern              = hostPattern;
 3704     pattern->patterns.host.patternSize         = (int) hostPatternSize;
 3705     pattern->patterns.path.pattern              = pathPattern;
 3706     pattern->patterns.path.patternSize         = (int) pathPatternSize;
 3707     pattern->patterns.scheme.pattern              = schemePattern;
 3708     pattern->patterns.scheme.patternSize         = (int) schemePatternSize;
 3709 
 3710     DetectorAppUrlList *urlList = &pConfig->httpPatternLists.appUrlList;
 3711 
 3712     /**first time usedCount and allocatedCount are both 0, urlPattern will be NULL.
 3713      * This case is same as malloc. In case of error, realloc will return NULL, and
 3714      * original urlPattern buffer is left untouched.
 3715      */
 3716     if (urlList->usedCount == urlList->allocatedCount)
 3717     {
 3718         tmp = realloc(urlList->urlPattern, (urlList->allocatedCount+URL_LIST_STEP_SIZE)*sizeof(*tmp));
 3719         if (!tmp)
 3720         {
 3721             FreeDetectorAppUrlPattern(pattern);
 3722             return 0;
 3723         }
 3724         urlList->urlPattern = tmp;
 3725         urlList->allocatedCount += URL_LIST_STEP_SIZE;
 3726     }
 3727 
 3728     urlList->urlPattern[urlList->usedCount++] = pattern;
 3729 
 3730     appInfoSetActive(service_id, true);
 3731     appInfoSetActive(client_id, true);
 3732     appInfoSetActive(payload_id, true);
 3733 
 3734     return 0;
 3735 }
 3736 
 3737 void CleanClientPortPatternList(tAppIdConfig *pConfig)
 3738 {
 3739     tPortPatternNode *tmp;
 3740 
 3741     if ( pConfig->clientPortPattern)
 3742     {
 3743         while ((tmp = pConfig->clientPortPattern->luaInjectedPatterns))
 3744         {
 3745             pConfig->clientPortPattern->luaInjectedPatterns = tmp->next;
 3746             free(tmp->pattern);
 3747             free(tmp->detectorName);
 3748             free(tmp);
 3749         }
 3750 
 3751         free(pConfig->clientPortPattern);
 3752     }
 3753 }
 3754 
 3755 void CleanServicePortPatternList(tAppIdConfig *pConfig)
 3756 {
 3757     tPortPatternNode *tmp;
 3758 
 3759     if ( pConfig->servicePortPattern)
 3760     {
 3761         while ((tmp = pConfig->servicePortPattern->luaInjectedPatterns))
 3762         {
 3763             pConfig->servicePortPattern->luaInjectedPatterns = tmp->next;
 3764             free(tmp->pattern);
 3765             free(tmp->detectorName);
 3766             free(tmp);
 3767         }
 3768 
 3769         free(pConfig->servicePortPattern);
 3770     }
 3771 }
 3772 
 3773 /* Add a port and pattern based detection for client application. Both port and pattern criteria
 3774  * must be met before client application is deemed detected.
 3775  *
 3776  * @param lua_State* - Lua state variable.
 3777  * @param proto/stack        - Protocol (IPPROTO_TCP/DC.ipproto.tcp (6) or
 3778  *                             IPPROTO_UDP/DC.ipproto.udp (17)).
 3779  * @param port/stack - port number to register.
 3780  * @param pattern/stack - pattern to be matched.
 3781  * @param patternLenght/stack - length of pattern
 3782  * @param offset/stack - offset into packet payload where matching should start.
 3783  * @param appId/stack        - App ID to use for this detector.
 3784  * @return int - Number of elements on stack, which is always 0.
 3785  */
 3786 static int addPortPatternClient(lua_State *L)
 3787 {
 3788     int index = 1;
 3789     tAppIdConfig *pConfig;
 3790     tPortPatternNode *pPattern;
 3791     uint8_t protocol;
 3792     uint16_t port;
 3793     const char*pattern;
 3794     size_t patternSize = 0;
 3795     unsigned position;
 3796     tAppId appId;
 3797 
 3798     /* Verify detector user data and that we are not in packet context */
 3799     DetectorUserData *detectorUserData = checkDetectorUserData(L, index++);
 3800     if (!detectorUserData)
 3801     {
 3802         _dpd.errMsg( "addPortPatternClient(): Invalid detector user data");
 3803         return 0;
 3804     }
 3805 
 3806     pConfig = detectorUserData->pDetector->pAppidNewConfig;
 3807     protocol = lua_tonumber(L, index++);
 3808     //port      = lua_tonumber(L, index++);
 3809     port = 0;
 3810     pattern = lua_tolstring(L, index++, &patternSize);
 3811     position = lua_tonumber(L, index++);
 3812     appId = lua_tointeger(L, index++);
 3813 
 3814     if (!pConfig->clientPortPattern)
 3815     {
 3816         if (!(pConfig->clientPortPattern = calloc(1, sizeof(*pConfig->clientPortPattern))))
 3817         {
 3818             _dpd.errMsg( "addPortPatternClient(): memory allocation failure");
 3819             return 0;
 3820         }
 3821     }
 3822     if (appId <= APP_ID_NONE || !pattern || !patternSize || (protocol != IPPROTO_TCP && protocol != IPPROTO_UDP))
 3823     {
 3824         _dpd.errMsg("addPortPatternClient(): Invalid input in %s\n", detectorUserData->pDetector->name);
 3825         return 0;
 3826     }
 3827     if (!(pPattern  = calloc(1, sizeof(*pPattern))))
 3828     {
 3829         _dpd.errMsg( "addPortPatternClient(): memory allocation failure");
 3830         return 0;
 3831     }
 3832     if (!(pPattern->pattern  = malloc(patternSize)))
 3833     {
 3834         _dpd.errMsg( "addPortPatternClient(): memory allocation failure");
 3835         free(pPattern);
 3836         return 0;
 3837     }
 3838 
 3839     pPattern->appId = appId;
 3840     pPattern->protocol = protocol;
 3841     pPattern->port = port;
 3842     memcpy(pPattern->pattern, pattern, patternSize);
 3843     pPattern->length = patternSize;
 3844     pPattern->offset = position;
 3845     if (!(pPattern->detectorName = strdup(detectorUserData->pDetector->name)))
 3846     {
 3847         _dpd.errMsg( "addPortPatternClient(): memory allocation failure");
 3848         free(pPattern->pattern);
 3849         free(pPattern);
 3850         return 0;
 3851     }
 3852 
 3853     //insert ports in order.
 3854     {
 3855         tPortPatternNode **prev;
 3856         tPortPatternNode **curr;
 3857 
 3858         prev = NULL;
 3859         for (curr = &pConfig->clientPortPattern->luaInjectedPatterns;
 3860                 *curr;
 3861                 prev = curr, curr = &((*curr)->next))
 3862         {
 3863             if (strcmp(pPattern->detectorName, (*curr)->detectorName) || pPattern->protocol < (*curr)->protocol
 3864                     || pPattern->port < (*curr)->port)
 3865                 break;
 3866         }
 3867         if (prev)
 3868         {
 3869             pPattern->next = (*prev)->next;
 3870             (*prev)->next = pPattern;
 3871         }
 3872         else
 3873         {
 3874             pPattern->next = *curr;
 3875             *curr = pPattern;
 3876         }
 3877     }
 3878 
 3879     appInfoSetActive(appId, true);
 3880 
 3881     return 0;
 3882 }
 3883 
 3884 /* Add a port and pattern based detection for service application. Both port and pattern criteria
 3885  * must be met before service application is deemed detected.
 3886  *
 3887  * @param lua_State* - Lua state variable.
 3888  * @param proto/stack        - Protocol (IPPROTO_TCP/DC.ipproto.tcp (6) or
 3889  *                             IPPROTO_UDP/DC.ipproto.udp (17)).
 3890  * @param port/stack - port number to register.
 3891  * @param pattern/stack - pattern to be matched.
 3892  * @param patternLenght/stack - length of pattern
 3893  * @param offset/stack - offset into packet payload where matching should start.
 3894  * @param appId/stack        - App ID to use for this detector.
 3895  * @return int - Number of elements on stack, which is always 0.
 3896  */
 3897 static int addPortPatternService(lua_State *L)
 3898 {
 3899     int index = 1;
 3900     size_t patternSize = 0;
 3901     tAppIdConfig *pConfig;
 3902     tPortPatternNode *pPattern;
 3903     uint8_t protocol;
 3904     uint16_t port;
 3905     const char *pattern;
 3906     unsigned position;
 3907     tAppId appId;
 3908 
 3909     /* Verify detector user data and that we are not in packet context */
 3910     DetectorUserData *detectorUserData = checkDetectorUserData(L, index++);
 3911     if (!detectorUserData)
 3912     {
 3913         _dpd.errMsg( "addPortPatternService(): Invalid detector user data");
 3914         return 0;
 3915     }
 3916 
 3917     pConfig = detectorUserData->pDetector->pAppidNewConfig;
 3918     protocol = lua_tonumber(L, index++);
 3919     port      = lua_tonumber(L, index++);
 3920     pattern = lua_tolstring(L, index++, &patternSize);
 3921     position = lua_tonumber(L, index++);
 3922     appId = lua_tointeger(L, index++);
 3923 
 3924     if (!pConfig->servicePortPattern)
 3925     {
 3926         if (!(pConfig->servicePortPattern = calloc(1, sizeof(*pConfig->servicePortPattern))))
 3927         {
 3928             _dpd.errMsg( "addPortPatternService(): memory allocation failure");
 3929             return 0;
 3930         }
 3931     }
 3932     if (!(pPattern = calloc(1, sizeof(*pPattern))))
 3933     {
 3934         _dpd.errMsg( "addPortPatternService(): memory allocation failure");
 3935         return 0;
 3936     }
 3937     if (!(pPattern->pattern  = malloc(patternSize)))
 3938     {
 3939         _dpd.errMsg( "addPortPatternService(): memory allocation failure");
 3940         free(pPattern);
 3941         return 0;
 3942     }
 3943 
 3944     pPattern->appId = appId;
 3945     pPattern->protocol = protocol;
 3946     pPattern->port = port;
 3947     memcpy(pPattern->pattern, pattern, patternSize);
 3948     pPattern->length = patternSize;
 3949     pPattern->offset = position;
 3950     if (!(pPattern->detectorName = strdup(detectorUserData->pDetector->name)))
 3951     {
 3952         _dpd.errMsg( "addPortPatternService(): memory allocation failure");
 3953         free(pPattern->pattern);
 3954         free(pPattern);
 3955         return 0;
 3956     }
 3957 
 3958     //insert ports in order.
 3959     {
 3960         tPortPatternNode **prev;
 3961         tPortPatternNode **curr;
 3962 
 3963         prev = NULL;
 3964         for (curr = &pConfig->servicePortPattern->luaInjectedPatterns;
 3965                 *curr;
 3966                 prev = curr, curr = &((*curr)->next))
 3967         {
 3968             if (strcmp(pPattern->detectorName, (*curr)->detectorName) || pPattern->protocol < (*curr)->protocol
 3969                     || pPattern->port < (*curr)->port)
 3970                 break;
 3971         }
 3972         if (prev)
 3973         {
 3974             pPattern->next = (*prev)->next;
 3975             (*prev)->next = pPattern;
 3976         }
 3977         else
 3978         {
 3979             pPattern->next = *curr;
 3980             *curr = pPattern;
 3981         }
 3982     }
 3983 
 3984     appInfoSetActive(appId, true);
 3985 
 3986     return 0;
 3987 }
 3988 
 3989 
 3990 /*Lua should inject patterns in <clientAppId, clientVersion, multi-Pattern> format. */
 3991 static int Detector_addSipServer(lua_State *L)
 3992 {
 3993     int index = 1;
 3994 
 3995     /* Verify detector user data and that we are not in packet context */
 3996     DetectorUserData *detectorUserData = checkDetectorUserData(L, index++);
 3997     if (!detectorUserData)
 3998     {
 3999         _dpd.errMsg( "Invalid HTTP detector user data addSipServer.");
 4000         return 0;
 4001     }
 4002 
 4003     u_int32_t client_app      = lua_tointeger(L, index++);
 4004     const char *clientVersion       = lua_tostring(L, index++);
 4005     if(!clientVersion )
 4006     {
 4007         _dpd.errMsg( "Invalid sip client version string.");
 4008         return 0;
 4009     }
 4010 
 4011     if (detectorUserData->pDetector->validateParams.pkt)
 4012     {
 4013         _dpd.errMsg("Invalid detector context addSipServer: client_app %u\n",client_app);
 4014         return 0;
 4015     }
 4016 
 4017     /* Verify that ua pattern is a valid string */
 4018     const char* uaPattern = lua_tostring(L, index++);
 4019     if(!uaPattern)
 4020     {
 4021         _dpd.errMsg( "Invalid sip ua pattern string.");
 4022         return 0;
 4023     }
 4024 
 4025     sipServerPatternAdd(client_app, clientVersion, uaPattern, &detectorUserData->pDetector->pAppidNewConfig->detectorSipConfig);
 4026 
 4027     appInfoSetActive(client_app, true);
 4028 
 4029     return 0;
 4030 }
 4031 
 4032 static inline int ConvertStringToAddress(const char * string, sfaddr_t * address)
 4033 {
 4034     int af;
 4035     struct in6_addr buf;
 4036 
 4037     if (strchr(string, ':'))
 4038         af = AF_INET6;
 4039     else if (strchr(string, '.'))
 4040         af = AF_INET;
 4041     else
 4042         return 0;
 4043 
 4044     if (inet_pton(af, string, &buf))
 4045     {
 4046         if (sfip_set_raw(address, &buf, af) != SFIP_SUCCESS)
 4047             return 0;
 4048     }
 4049     else
 4050         return 0;
 4051 
 4052     return 1;    // success
 4053 }
 4054 
 4055 /**Creates a future flow based on the current flow.  When the future flow is
 4056  * seen, the app ID will simply be declared with the info given here.
 4057  *
 4058  * @param Lua_State* - Lua state variable.
 4059  * @param detector/stack - detector object.
 4060  * @param client_addr/stack - client address of the future flow
 4061  * @param client_port/stack - client port of the the future flow (can use 0 for wildcard here)
 4062  * @param server_addr/stack - server address of the future flow
 4063  * @param server_port/stack - server port of the future flow
 4064  * @param proto/stack - protocol type (see define IPPROTO_xxxx in /usr/include/netinet/in.h)
 4065  * @param service_app_id/stack - service app ID to declare for future flow (can be 0 for none)
 4066  * @param client_app_id/stack - client app ID to declare for future flow (can be 0 for none)
 4067  * @param payload_app_id/stack - payload app ID to declare for future flow (can be 0 for none)
 4068  * @param app_id_to_snort/stack - AppID's app ID entry to convert to Snort app ID (see note below)
 4069  * @return int - number of elements on stack, which is 1 if successful, 0 otherwise.
 4070  *
 4071  * Notes: For app_id_to_snort, use the app ID that AppID knows about (it'll
 4072  * probably be a repeat of one of the other 3 app IDs given here).  For
 4073  * example, for "FTP Data", use 166.  Internally, this'll be converted to the
 4074  * app ID that Snort recognizes ("ftp-data").  For this to really mean
 4075  * anything, the app IDs entry in appMapping.data should have a Snort app ID
 4076  * defined.
 4077  *
 4078  * Example: createFutureFlow("192.168.0.200", 0, "192.168.0.100", 20, 6, 166, 0, 0, 166)
 4079  */
 4080 static int createFutureFlow (lua_State *L)
 4081 {
 4082     sfaddr_t client_addr;
 4083     sfaddr_t server_addr;
 4084     uint8_t proto;
 4085     uint16_t client_port, server_port;
 4086     DetectorUserData *detectorUserData = NULL;
 4087     char *pattern;
 4088     tAppId service_app_id, client_app_id, payload_app_id, app_id_to_snort;
 4089     int16_t snort_app_id;
 4090     tAppIdData *fp;
 4091 
 4092     detectorUserData = checkDetectorUserData(L, 1);
 4093 
 4094     /*check inputs and whether this function is called in context of a packet */
 4095     if (!detectorUserData || !detectorUserData->pDetector->validateParams.pkt)
 4096     {
 4097         return 0;
 4098     }
 4099 
 4100     pattern = (char *)lua_tostring(L, 2);
 4101     if (!ConvertStringToAddress(pattern, &client_addr))
 4102         return 0;
 4103 
 4104     client_port = lua_tonumber(L, 3);
 4105 
 4106     pattern = (char *)lua_tostring(L, 4);
 4107     if (!ConvertStringToAddress(pattern, &server_addr))
 4108         return 0;
 4109 
 4110     server_port = lua_tonumber(L, 5);
 4111 
 4112     proto = lua_tonumber(L, 6);
 4113 
 4114     service_app_id = lua_tointeger(L, 7);
 4115     client_app_id  = lua_tointeger(L, 8);
 4116     payload_app_id = lua_tointeger(L, 9);
 4117 
 4118     app_id_to_snort = lua_tointeger(L, 10);
 4119     if (app_id_to_snort > APP_ID_NONE)
 4120     {
 4121         AppInfoTableEntry* entry = appInfoEntryGet(app_id_to_snort, appIdActiveConfigGet());
 4122         if (NULL == entry)
 4123             return 0;
 4124         snort_app_id = entry->snortId;
 4125     }
 4126     else
 4127     {
 4128         snort_app_id = 0;
 4129     }
 4130 
 4131     fp = AppIdEarlySessionCreate(detectorUserData->pDetector->validateParams.flowp,
 4132                                  detectorUserData->pDetector->validateParams.pkt,
 4133                                  &client_addr, client_port, &server_addr, server_port, proto,
 4134                                  snort_app_id,
 4135                                  APPID_EARLY_SESSION_FLAG_FW_RULE);
 4136     if (fp)
 4137     {
 4138         fp->serviceAppId = service_app_id;
 4139         fp->clientAppId  = client_app_id;
 4140         fp->payloadAppId = payload_app_id;
 4141         setAppIdFlag(fp, APPID_SESSION_SERVICE_DETECTED | APPID_SESSION_NOT_A_SERVICE | APPID_SESSION_PORT_SERVICE_DONE);
 4142         fp->rnaServiceState = RNA_STATE_FINISHED;
 4143         fp->rnaClientState  = RNA_STATE_FINISHED;
 4144 
 4145         return 1;
 4146     }
 4147     else
 4148         return 0;
 4149 }
 4150 
 4151 static int isMidStreamSession(lua_State *L)
 4152 {
 4153     DetectorUserData *detectorUserData = NULL;
 4154 
 4155     detectorUserData = checkDetectorUserData(L, 1);
 4156 
 4157     /*check inputs and whether this function is called in context of a packet */
 4158     if (!detectorUserData || !detectorUserData->pDetector->validateParams.pkt)
 4159     {
 4160         lua_pushnumber(L, -1);
 4161         return -1;
 4162     }
 4163 
 4164     if (_dpd.sessionAPI->get_session_flags(detectorUserData->pDetector->validateParams.pkt->stream_session) & SSNFLAG_MIDSTREAM)
 4165     {
 4166         lua_pushnumber(L, 1);
 4167         return 1;
 4168     }
 4169 
 4170     lua_pushnumber(L, 0);
 4171     return 0;
 4172 }
 4173 
 4174 /* Check if traffic is going through an HTTP proxy */
 4175 static int isHttpTunnel(lua_State *L)
 4176 {
 4177     DetectorUserData *detectorUserData = NULL;
 4178 
 4179     detectorUserData = checkDetectorUserData(L, 1);
 4180 
 4181     /*check inputs and whether this function is called in context of a packet */
 4182     if (!detectorUserData || !detectorUserData->pDetector->validateParams.pkt)
 4183         return -1;
 4184 
 4185     httpSession *hsession = detectorUserData->pDetector->validateParams.flowp->hsession;
 4186     if (hsession)
 4187     {
 4188         tunnelDest *tunDest = hsession->tunDest;
 4189         if (tunDest)
 4190         {
 4191             lua_pushboolean(L, 1);
 4192             return 1;
 4193         }
 4194     }
 4195 
 4196     lua_pushboolean(L, 0);
 4197     return 0;
 4198 }
 4199 
 4200 /* Get destination IP tunneled through a proxy */
 4201 static int getHttpTunneledIp(lua_State* L)
 4202 {
 4203     DetectorUserData *detectorUserData = NULL;
 4204 
 4205     detectorUserData = checkDetectorUserData(L, 1);
 4206     
 4207     /*check inputs and whether this function is called in context of a packet */
 4208     if (!detectorUserData || !detectorUserData->pDetector->validateParams.pkt)
 4209         return -1;
 4210 
 4211     httpSession *hsession = detectorUserData->pDetector->validateParams.flowp->hsession;
 4212     if (hsession)
 4213     {
 4214         tunnelDest *tunDest = hsession->tunDest;
 4215         if (!tunDest)
 4216             lua_pushnumber(L, 0);
 4217         else 
 4218             lua_pushnumber(L, sfaddr_get_ip4_value(&(tunDest->ip)));
 4219     }
 4220     
 4221     return 1;
 4222 }
 4223 
 4224 /* Get port tunneled through a proxy */
 4225 static int getHttpTunneledPort(lua_State* L)
 4226 {
 4227     DetectorUserData *detectorUserData = NULL;
 4228 
 4229     detectorUserData = checkDetectorUserData(L, 1);
 4230     
 4231     /*check inputs and whether this function is called in context of a packet */
 4232     if (!detectorUserData || !detectorUserData->pDetector->validateParams.pkt)
 4233         return -1;
 4234 
 4235     httpSession *hsession = detectorUserData->pDetector->validateParams.flowp->hsession;
 4236     if (hsession)
 4237     {
 4238         tunnelDest *tunDest = hsession->tunDest;
 4239         if (!tunDest)
 4240             lua_pushnumber(L, 0);
 4241         else
 4242             lua_pushnumber(L, tunDest->port);
 4243     }
 4244     
 4245     return 1;
 4246 }
 4247 
 4248 /*Lua should inject patterns in <clientAppId, classId> format. */
 4249 static int Detector_addCipConnectionClass(lua_State *L)
 4250 {
 4251     int index = 1;
 4252 
 4253     DetectorUserData *detectorUserData = checkDetectorUserData(L, index++);
 4254     if (!detectorUserData || detectorUserData->pDetector->validateParams.pkt)
 4255     {
 4256         _dpd.errMsg("%s: Invalid detector user data or context.\n", __func__);
 4257         return -1;
 4258     }
 4259 
 4260     uint32_t appId = lua_tointeger(L, index++);
 4261     uint32_t classId = lua_tointeger(L, index++);
 4262 
 4263     if (CipAddConnectionClass(appId, classId) == -1)
 4264     {
 4265         return -1;
 4266     }
 4267 
 4268     appInfoSetActive(appId, true);
 4269 
 4270     return 0;
 4271 }
 4272 
 4273 /*Lua should inject patterns in <clientAppId, classId, serviceId> format. */
 4274 static int Detector_addCipPath(lua_State *L)
 4275 {
 4276     int index = 1;
 4277 
 4278     DetectorUserData *detectorUserData = checkDetectorUserData(L, index++);
 4279     if (!detectorUserData || detectorUserData->pDetector->validateParams.pkt)
 4280     {
 4281         _dpd.errMsg("%s: Invalid detector user data or context.\n", __func__);
 4282         return -1;
 4283     }
 4284 
 4285     uint32_t appId = lua_tointeger(L, index++);
 4286     uint32_t classId = lua_tointeger(L, index++);
 4287     uint8_t serviceId = lua_tointeger(L, index++);
 4288 
 4289     if (CipAddPath(appId, classId, serviceId) == -1)
 4290     {
 4291         return -1;
 4292     }
 4293 
 4294     appInfoSetActive(appId, true);
 4295 
 4296     return 0;
 4297 }
 4298 
 4299 /*Lua should inject patterns in <clientAppId, classId, isClassInstance, attributeId> format. */
 4300 static int Detector_addCipSetAttribute(lua_State *L)
 4301 {
 4302     int index = 1;
 4303 
 4304     DetectorUserData *detectorUserData = checkDetectorUserData(L, index++);
 4305     if (!detectorUserData || detectorUserData->pDetector->validateParams.pkt)
 4306     {
 4307         _dpd.errMsg("%s: Invalid detector user data or context.\n", __func__);
 4308         return -1;
 4309     }
 4310 
 4311     uint32_t appId = lua_tointeger(L, index++);
 4312     uint32_t classId = lua_tointeger(L, index++);
 4313     bool isClassInstance = lua_toboolean(L, index++);
 4314     uint32_t attributeId = lua_tointeger(L, index++);
 4315 
 4316     if (CipAddSetAttribute(appId, classId, isClassInstance, attributeId) == -1)
 4317     {
 4318         return -1;
 4319     }
 4320 
 4321     appInfoSetActive(appId, true);
 4322 
 4323     return 0;
 4324 }
 4325 
 4326 
 4327 /*Lua should inject patterns in <clientAppId, serviceId> format. */
 4328 static int Detector_addCipExtendedSymbolService(lua_State *L)
 4329 {
 4330     int index = 1;
 4331 
 4332     DetectorUserData *detectorUserData = checkDetectorUserData(L, index++);
 4333     if (!detectorUserData || detectorUserData->pDetector->validateParams.pkt)
 4334     {
 4335         _dpd.errMsg("%s: Invalid detector user data or context.\n", __func__);
 4336         return -1;
 4337     }
 4338 
 4339     uint32_t appId = lua_tointeger(L, index++);
 4340     uint8_t serviceId = lua_tointeger(L, index++);
 4341 
 4342     if (CipAddExtendedSymbolService(appId, serviceId) == -1)
 4343     {
 4344         return -1;
 4345     }
 4346 
 4347     appInfoSetActive(appId, true);
 4348 
 4349     return 0;
 4350 }
 4351 
 4352 /*Lua should inject patterns in <clientAppId, serviceId> format. */
 4353 static int Detector_addCipService(lua_State *L)
 4354 {
 4355     int index = 1;
 4356 
 4357     DetectorUserData *detectorUserData = checkDetectorUserData(L, index++);
 4358     if (!detectorUserData || detectorUserData->pDetector->validateParams.pkt)
 4359     {
 4360         _dpd.errMsg("%s: Invalid detector user data or context.\n", __func__);
 4361         return -1;
 4362     }
 4363 
 4364     uint32_t appId = lua_tointeger(L, index++);
 4365     uint16_t serviceId = lua_tointeger(L, index++);
 4366 
 4367     if (CipAddService(appId, serviceId) == -1)
 4368     {
 4369         return -1;
 4370     }
 4371 
 4372     appInfoSetActive(appId, true);
 4373 
 4374     return 0;
 4375 }
 4376 
 4377 /*Lua should inject patterns in <clientAppId, enipCommandId> format. */
 4378 static int Detector_addEnipCommand(lua_State *L)
 4379 {
 4380     int index = 1;
 4381 
 4382     DetectorUserData *detectorUserData = checkDetectorUserData(L, index++);
 4383     if (!detectorUserData || detectorUserData->pDetector->validateParams.pkt)
 4384     {
 4385         _dpd.errMsg("%s: Invalid detector user data or context.\n", __func__);
 4386         return -1;
 4387     }
 4388 
 4389     uint32_t appId = lua_tointeger(L, index++);
 4390     uint16_t commandId = lua_tointeger(L, index++);
 4391 
 4392     if (CipAddEnipCommand(appId, commandId) == -1)
 4393     {
 4394         return -1;
 4395     }
 4396 
 4397     appInfoSetActive(appId, true);
 4398 
 4399     return 0;
 4400 }
 4401 
 4402 static const luaL_Reg Detector_methods[] = {
 4403   /* Obsolete API names.  No longer use these!  They are here for backward
 4404    * compatibility and will eventually be removed. */
 4405   /*  - "memcmp" is now "matchSimplePattern" (below) */
 4406   {"memcmp",                   Detector_memcmp},
 4407   /*  - "getProtocolType" is now "getL4Protocol" (below) */
 4408   {"getProtocolType",          Detector_getProtocolType},
 4409   /*  - "inCompatibleData" is now "markIncompleteData" (below) */
 4410   {"inCompatibleData",         service_inCompatibleData},
 4411   /*  - "addDataId" is now "addAppIdDataToFlow" (below) */
 4412   {"addDataId",                service_addDataId},
 4413   /*  - "service_inCompatibleData" is now "service_markIncompleteData" (below) */
 4414   {"service_inCompatibleData", service_inCompatibleData},
 4415   /*  - "service_addDataId" is now "service_addAppIdDataToFlow" (below) */
 4416   {"service_addDataId",        service_addDataId},
 4417 
 4418   {"getPacketSize",            Detector_getPacketSize},
 4419   {"getPacketDir",             Detector_getPacketDir},
 4420   {"matchSimplePattern",       Detector_memcmp},
 4421   {"getPcreGroups",            Detector_getPcreGroups},
 4422   {"getL4Protocol",            Detector_getProtocolType},
 4423   {"getPktSrcAddr",            Detector_getPktSrcIPAddr},
 4424   {"getPktDstAddr",            Detector_getPktDstIPAddr},
 4425   {"getPktSrcPort",            Detector_getPktSrcPort},
 4426   {"getPktDstPort",            Detector_getPktDstPort},
 4427   {"getPktCount",              Detector_getPktCount},
 4428   {"getFlow",                  Detector_getFlow},
 4429   {"htons",                    Detector_htons},
 4430   {"htonl",                    Detector_htonl},
 4431   {"log",                      Detector_logMessage},
 4432   {"addHttpPattern",           Detector_addHttpPattern},
 4433   {"addAppUrl",                Detector_addAppUrl},
 4434   {"addRTMPUrl",               Detector_addRTMPUrl},
 4435   {"addContentTypePattern",    Detector_addContentTypePattern},
 4436   {"addSSLCertPattern",        Detector_addSSLCertPattern},
 4437   {"addSipUserAgent",          Detector_addSipUserAgent},
 4438   {"addSipServer",             Detector_addSipServer},
 4439   {"addSSLCnamePattern",       Detector_addSSLCnamePattern},
 4440   {"addHostPortApp",           Detector_addHostPortApp},
 4441   {"addHostPortAppDynamic",    Detector_addHostPortAppDynamic},
 4442   {"addDNSHostPattern",        Detector_addDNSHostPattern},
 4443   {"registerClientDetectorCallback",    Detector_registerClientCallback},
 4444   {"registerServiceDetectorCallback",   Detector_registerServiceCallback},
 4445 
 4446   /* CIP registration */
 4447   {"addCipConnectionClass",    Detector_addCipConnectionClass},
 4448   {"addCipPath",               Detector_addCipPath},
 4449   {"addCipSetAttribute",       Detector_addCipSetAttribute},
 4450   {"addCipExtendedSymbolService", Detector_addCipExtendedSymbolService},
 4451   {"addCipService",            Detector_addCipService},
 4452   {"addEnipCommand",           Detector_addEnipCommand},
 4453 
 4454   /*Obsolete - new detectors should not use this API */
 4455   {"init",                     service_init},
 4456   {"registerPattern",          service_registerPattern},
 4457   {"getServiceID",             service_getServiceId},
 4458   {"addPort",                  service_addPorts},
 4459   {"removePort",               service_removePorts},
 4460   {"setServiceName",           service_setServiceName},
 4461   {"getServiceName",           service_getServiceName},
 4462   {"isCustomDetector",         service_isCustomDetector},
 4463   {"setValidator",             service_setValidator},
 4464   {"addService",               service_addService},
 4465   {"failService",              service_failService},
 4466   {"inProcessService",         service_inProcessService},
 4467   {"markIncompleteData",       service_inCompatibleData},
 4468   {"analyzePayload",           service_analyzePayload},
 4469   {"addAppIdDataToFlow",       service_addDataId},
 4470 
 4471   /*service API */
 4472   {"service_init",             service_init},
 4473   {"service_registerPattern",  service_registerPattern},
 4474   {"service_getServiceId",     service_getServiceId},
 4475   {"service_addPort",          service_addPorts},
 4476   {"service_removePort",       service_removePorts},
 4477   {"service_setServiceName",   service_setServiceName},
 4478   {"service_getServiceName",   service_getServiceName},
 4479   {"service_isCustomDetector", service_isCustomDetector},
 4480   {"service_setValidator",     service_setValidator},
 4481   {"service_addService",       service_addService},
 4482   {"service_failService",      service_failService},
 4483   {"service_inProcessService", service_inProcessService},
 4484   {"service_markIncompleteData", service_inCompatibleData},
 4485   {"service_analyzePayload",   service_analyzePayload},
 4486   {"service_addAppIdDataToFlow", service_addDataId},
 4487   {"service_addClient",        service_addClient},
 4488 
 4489   /*client init API */
 4490   {"client_init",              client_init},
 4491   {"client_registerPattern",   client_registerPattern},
 4492   {"client_getServiceId",      service_getServiceId},
 4493 
 4494   /*client service API */
 4495   {"client_addApp",            client_addApp},
 4496   {"client_addInfo",           client_addInfo},
 4497   {"client_addUser",           client_addUser},
 4498   {"client_addPayload",        client_addPayload},
 4499 
 4500   //HTTP Multi Pattern engine
 4501   {"CHPCreateApp",             Detector_CHPCreateApp},
 4502   {"CHPAddAction",             Detector_CHPAddAction},
 4503   {"CHPMultiCreateApp",        Detector_CHPMultiCreateApp}, // allows multiple detectors, same appId
 4504   {"CHPMultiAddAction",        Detector_CHPMultiAddAction},
 4505 
 4506   //App Forecasting engine
 4507   {"AFAddApp",                 Detector_AFAddApp},
 4508 
 4509   {"portOnlyService",          Detector_portOnlyService},
 4510 
 4511   /* Length-based detectors. */
 4512   {"AddLengthBasedDetector",   Detector_lengthAppCacheAdd},
 4513 
 4514   {"registerAppId" ,           common_registerAppId},
 4515 
 4516   {"open_createApp",           openCreateApp},
 4517   {"open_addClientApp",        openAddClientApp},
 4518   {"open_addServiceApp",       openAddServiceApp},
 4519   {"open_addPayloadApp",       openAddPayloadApp},
 4520   {"open_addHttpPattern",      openAddHttpPattern},
 4521   {"open_addUrlPattern",       openAddUrlPattern},
 4522 
 4523   {"addPortPatternClient",     addPortPatternClient},
 4524   {"addPortPatternService",    addPortPatternService},
 4525 
 4526   {"createFutureFlow",         createFutureFlow},
 4527   {"isMidStreamSession",       isMidStreamSession},
 4528 
 4529   { "isHttpTunnel",             isHttpTunnel },
 4530   { "getHttpTunneledIp",        getHttpTunneledIp },
 4531   { "getHttpTunneledPort",      getHttpTunneledPort },
 4532 
 4533   {0, 0}
 4534 };
 4535 
 4536 /**This function performs a clean exit on an api instance. It is called when RNA is performing
 4537  * a clean exit.
 4538  */
 4539 void Detector_fini(void *data)
 4540 {
 4541     lua_State *myLuaState;
 4542     Detector *detector = (Detector*) data;
 4543 
 4544 #ifdef LUA_DETECTOR_DEBUG
 4545     _dpd.debugMsg(DEBUG_LOG,"Finishing detector %s\n",detector->server.serviceModule.name);
 4546 #endif
 4547 
 4548     myLuaState = detector->myLuaState;
 4549 
 4550     if (detector->packageInfo.server.cleanFunctionName && lua_checkstack(myLuaState, 1))
 4551     {
 4552         lua_getglobal(myLuaState, detector->packageInfo.server.cleanFunctionName);
 4553 
 4554         if (lua_pcall(myLuaState, 0, 0, 0 ))
 4555         {
 4556              /*See comment at first lua_pcall() */
 4557 #ifdef LUA_DETECTOR_DEBUG
 4558             _dpd.errMsg( "%s: error running %s in lua: %s", detector->server.serviceModule.name,
 4559                     detector->packageInfo.server.cleanFunctionName, lua_tostring(myLuaState, -1));
 4560 #endif
 4561         }
 4562     }
 4563     else if (detector->packageInfo.client.cleanFunctionName && lua_checkstack(myLuaState, 1))
 4564     {
 4565         lua_getglobal(myLuaState, detector->packageInfo.client.cleanFunctionName);
 4566 
 4567         if (lua_pcall(myLuaState, 0, 0, 0 ))
 4568         {
 4569              /*See comment at first lua_pcall() */
 4570 #ifdef LUA_DETECTOR_DEBUG
 4571             _dpd.errMsg( "%s: error running %s in lua: %s", detector->server.serviceModule.name,
 4572                     detector->packageInfo.client.cleanFunctionName, lua_tostring(myLuaState, -1));
 4573 #endif
 4574         }
 4575     }
 4576 
 4577     freeDetector(detector);
 4578 
 4579     /*lua_close will perform garbage collection after killing lua script. */
 4580     /**Design: Lua_state does not allow me to store user variables so detectors store lua_state.
 4581      * There is one lua_state for each lua file, which can have only one
 4582      * detectors. So if lua detector creates a detector, registers a pattern
 4583      * and then loses reference then lua will garbage collect but we should not free the buffer.
 4584      *
 4585      */
 4586     lua_close(myLuaState);
 4587 }
 4588 
 4589 
 4590 /**Garbage collector hook function. Called when Lua side garbage collects detector api instance. Current design is to allocate
 4591  * one of each luaState, detector and detectorUserData buffers, and hold these buffers till RNA exits. SigHups processing
 4592  * reuses the buffers and calls DetectorInit to reinitialize. RNA ensures that DetectorUserData is not garbage collected, by
 4593  * creating a reference in LUA_REGISTRY table. The reference is released only on RNA exit.
 4594  *
 4595  * If in future, one needs to free any of these buffers then one should consider references to detector buffer in  RNAServiceElement
 4596  * stored in flows and hostServices  data structures. Other detectors at this time create one static instance for the lifetime of RNA,
 4597  * and therefore we have adopted the same principle for Lua Detecotors.
 4598  */
 4599 static int Detector_gc (
 4600         lua_State *L
 4601         )
 4602 {
 4603     DetectorUserData *detectorUserData =  toDetectorUserData(L, -1);
 4604 
 4605     if (detectorUserData)
 4606     {
 4607 #ifdef LUA_DETECTOR_DEBUG
 4608         _dpd.debugMsg(DEBUG_LOG,"DetectorUserData %p: freeing\n\n",detectorUserData);
 4609 #endif
 4610 
 4611     }
 4612 
 4613     return 0;
 4614 }
 4615 
 4616 /*convert detector to string for printing */
 4617 static int Detector_tostring (
 4618         lua_State *L
 4619         )
 4620 {
 4621   char buff[32];
 4622   snprintf(buff, sizeof(buff), "%p", toDetectorUserData(L, 1));
 4623   lua_pushfstring(L, "Detector (%s)", buff);
 4624   return 1;
 4625 }
 4626 
 4627 static const luaL_Reg Detector_meta[] = {
 4628   {"__gc",       Detector_gc},
 4629   {"__tostring", Detector_tostring},
 4630   {0, 0}
 4631 };
 4632 
 4633 
 4634 /**Registers C functions as an API, enabling Lua detector to call these functions. This function
 4635  * should be called once before loading any lua detectors. This function itself is not part of API
 4636  * and therefore can not be called by a Lua detection.
 4637  *
 4638  * @param Lua_State* - Lua state variable.
 4639  * @param detector/stack - detector object
 4640  * @return int - Number of elements on stack, which is 1 if successful, 0 otherwise.
 4641  * @return methodArray/stack - array of newly created methods
 4642  */
 4643 int Detector_register (
 4644         lua_State *L
 4645         )
 4646 {
 4647 
 4648   /* populates a new table with Detector_methods (method_table), add the table to the globals and stack*/
 4649   luaL_openlib(L, DETECTOR, Detector_methods, 0);
 4650 
 4651   /* create metatable for Foo, add it to the Lua registry, metatable on stack */
 4652   luaL_newmetatable(L, DETECTOR);
 4653 
 4654   /* populates table on stack with Detector_meta methods, puts the metatable on stack*/
 4655   luaL_openlib(L, NULL, Detector_meta, 0);
 4656 
 4657   lua_pushliteral(L, "__index");
 4658   lua_pushvalue(L, -3);               /* dup methods table*/
 4659   lua_settable(L, -3);                  /* metatable.__index = methods */
 4660 
 4661   lua_pushliteral(L, "__metatable");
 4662   lua_pushvalue(L, -3);               /* dup methods table*/
 4663   lua_settable(L, -3);                  /* hide metatable:
 4664                                            metatable.__metatable = methods */
 4665   lua_pop(L, 1);                      /* drop metatable */
 4666   return 1;                           /* return methods on the stack */
 4667 
 4668 
 4669 }
 4670 
 4671 /** @} */ /* end of LuaDetectorBaseApi */
 4672 
 4673 static void FreeHTTPListElement(HTTPListElement *element)
 4674 {
 4675     if (element)
 4676     {
 4677         if (element->detectorHTTPPattern.pattern)
 4678             free(element->detectorHTTPPattern.pattern);
 4679         free(element);
 4680     }
 4681 }
 4682 
 4683 static void FreeCHPAppListElement (CHPListElement *element)
 4684 {
 4685     if (element)
 4686     {
 4687         if (element->chp_action.pattern) free(element->chp_action.pattern);
 4688         if (element->chp_action.action_data) free(element->chp_action.action_data);
 4689         free (element);
 4690     }
 4691 }
 4692 
 4693 static void FreeDetectorAppUrlPattern(DetectorAppUrlPattern *pattern)
 4694 {
 4695     if (pattern)
 4696     {
 4697         if (pattern->userData.query.pattern)
 4698             free(*(void **)&pattern->userData.query.pattern);
 4699         if (pattern->patterns.host.pattern)
 4700             free(*(void **)&pattern->patterns.host.pattern);
 4701         if (pattern->patterns.path.pattern)
 4702             free(*(void **)&pattern->patterns.path.pattern);
 4703         if (pattern->patterns.scheme.pattern)
 4704             free(*(void **)&pattern->patterns.scheme.pattern);
 4705         free(pattern);
 4706     }
 4707 }
 4708 
 4709 void CleanHttpPatternLists(tAppIdConfig *pConfig)
 4710 {
 4711     HTTPListElement *element;
 4712     CHPListElement *chpe;
 4713     size_t i;
 4714 
 4715     for (i = 0; i < pConfig->httpPatternLists.appUrlList.usedCount; i++)
 4716     {
 4717         FreeDetectorAppUrlPattern(pConfig->httpPatternLists.appUrlList.urlPattern[i]);
 4718         pConfig->httpPatternLists.appUrlList.urlPattern[i] = NULL;
 4719     }
 4720     for (i = 0; i < pConfig->httpPatternLists.RTMPUrlList.usedCount; i++)
 4721     {
 4722         FreeDetectorAppUrlPattern(pConfig->httpPatternLists.RTMPUrlList.urlPattern[i]);
 4723         pConfig->httpPatternLists.RTMPUrlList.urlPattern[i] = NULL;
 4724     }
 4725     if (pConfig->httpPatternLists.appUrlList.urlPattern)
 4726     {
 4727         free(pConfig->httpPatternLists.appUrlList.urlPattern);
 4728         pConfig->httpPatternLists.appUrlList.urlPattern = NULL;
 4729     }
 4730     pConfig->httpPatternLists.appUrlList.allocatedCount = 0;
 4731     if (pConfig->httpPatternLists.RTMPUrlList.urlPattern)
 4732     {
 4733         free(pConfig->httpPatternLists.RTMPUrlList.urlPattern);
 4734         pConfig->httpPatternLists.RTMPUrlList.urlPattern = NULL;
 4735     }
 4736     pConfig->httpPatternLists.RTMPUrlList.allocatedCount = 0;
 4737     pConfig->httpPatternLists.appUrlList.usedCount = 0;
 4738     pConfig->httpPatternLists.RTMPUrlList.usedCount = 0;
 4739     while ((element = pConfig->httpPatternLists.clientAgentPatternList))
 4740     {
 4741         pConfig->httpPatternLists.clientAgentPatternList = element->next;
 4742         FreeHTTPListElement(element);
 4743     }
 4744     while ((element = pConfig->httpPatternLists.hostPayloadPatternList))
 4745     {
 4746         pConfig->httpPatternLists.hostPayloadPatternList = element->next;
 4747         FreeHTTPListElement(element);
 4748     }
 4749     while ((element = pConfig->httpPatternLists.urlPatternList))
 4750     {
 4751         pConfig->httpPatternLists.urlPatternList = element->next;
 4752         FreeHTTPListElement(element);
 4753     }
 4754     while ((element = pConfig->httpPatternLists.contentTypePatternList))
 4755     {
 4756         pConfig->httpPatternLists.contentTypePatternList = element->next;
 4757         FreeHTTPListElement(element);
 4758     }
 4759     while ((chpe = pConfig->httpPatternLists.chpList))
 4760     {
 4761         pConfig->httpPatternLists.chpList = chpe->next;
 4762         FreeCHPAppListElement(chpe);
 4763     }
 4764 }
 4765