diff --git a/configure.ac b/configure.ac index 8051e8a11d..971786aa50 100644 --- a/configure.ac +++ b/configure.ac @@ -1383,6 +1383,46 @@ AC_INIT(configure.ac) fi fi + # libgeoip + AC_ARG_ENABLE(geoip, + [ --enable-geoip Enable GeoIP support], + [ enable_geoip="yes"], + [ enable_geoip="no"]) + AC_ARG_WITH(libgeoip_includes, + [ --with-libgeoip-includes=DIR libgeoip include directory], + [with_libgeoip_includes="$withval"],[with_libgeoip_includes="no"]) + AC_ARG_WITH(libgeoip_libraries, + [ --with-libgeoip-libraries=DIR libgeoip library directory], + [with_libgeoip_libraries="$withval"],[with_libgeoip_libraries="no"]) + + if test "$enable_geoip" = "yes"; then + if test "$with_libgeoip_includes" != "no"; then + CPPFLAGS="${CPPFLAGS} -I${with_libgeoip_includes}" + fi + + AC_CHECK_HEADER(GeoIP.h,GEOIP="yes",GEOIP="no") + if test "$GEOIP" = "yes"; then + if test "$with_libgeoip_libraries" != "no"; then + LDFLAGS="${LDFLAGS} -L${with_libgeoip_libraries}" + fi + AC_CHECK_LIB(GeoIP, GeoIP_country_code_by_ipnum,, GEOIP="no") + fi + if test "$GEOIP" = "no"; then + echo + echo " ERROR! libgeoip library not found, go get it" + echo " from http://www.maxmind.com/en/geolite or your distribution:" + echo + echo " Ubuntu: apt-get install libgeoip-dev" + echo + exit 1 + fi + if test "$GEOIP" = "yes"; then + AC_DEFINE([HAVE_GEOIP],[1],[libgeoip available]) + enable_geoip="yes" + fi + fi + + # get revision if test -f ./revision; then REVISION=`cat ./revision` @@ -1467,6 +1507,7 @@ Suricata Configuration: Prelude support: ${enable_prelude} PCRE jit: ${pcre_jit_available} libluajit: ${enable_luajit} + libgeoip: ${enable_geoip} Non-bundled htp: ${enable_non_bundled_htp} Old barnyard2 support: ${enable_old_barnyard2} CUDA enabled: ${enable_cuda} diff --git a/src/Makefile.am b/src/Makefile.am index 0910e06955..4278fca5dd 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -119,6 +119,7 @@ detect-flowvar.c detect-flowvar.h \ detect-fragbits.c detect-fragbits.h \ detect-fragoffset.c detect-fragoffset.h \ detect-ftpbounce.c detect-ftpbounce.h \ +detect-geoip.c detect-geoip.h \ detect-gid.c detect-gid.h \ detect-http-client-body.c detect-http-client-body.h \ detect-http-cookie.c detect-http-cookie.h \ diff --git a/src/detect-geoip.c b/src/detect-geoip.c new file mode 100644 index 0000000000..5c6adddd45 --- /dev/null +++ b/src/detect-geoip.c @@ -0,0 +1,592 @@ +/* Copyright (C) 2012 Open Information Security Foundation + * + * You can copy, redistribute or modify this Program under the terms of + * the GNU General Public License version 2 as published by the Free + * Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * version 2 along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +/** + * \file + * + * \author Ignacio Sanchez + * + * Implements the geoip keyword. + */ + +#include "suricata-common.h" +#include "debug.h" +#include "decode.h" +#include "detect.h" + +#include "detect-parse.h" +#include "detect-engine.h" +#include "detect-engine-mpm.h" + +#include "detect-geoip.h" + +#include "util-unittest.h" +#include "util-unittest-helper.h" + +#ifndef HAVE_GEOIP + +static int DetectGeoipSetupNoSupport (DetectEngineCtx *a, Signature *b, char *c) { + SCLogError(SC_ERR_NO_GEOIP_SUPPORT, "no GeoIP support built in, needed for geoip keyword"); + return -1; +} + +/** + * \brief Registration function for geoip keyword (no libgeoip support) + * \todo add support for src_only and dst_only + */ +void DetectGeoipRegister(void) +{ + sigmatch_table[DETECT_GEOIP].name = "geoip"; + sigmatch_table[DETECT_GEOIP].Setup = DetectGeoipSetupNoSupport; + sigmatch_table[DETECT_GEOIP].Free = NULL; + sigmatch_table[DETECT_GEOIP].RegisterTests = NULL; +} + +#else /* HAVE_GEOIP */ + +#include + + +static int DetectGeoipMatch(ThreadVars *, DetectEngineThreadCtx *, Packet *, + Signature *, SigMatch *); +static int DetectGeoipSetup(DetectEngineCtx *, Signature *, char *); +static void DetectGeoipRegisterTests(void); +static void DetectGeoipDataFree(void *); + +/** + * \brief Registration function for geoip keyword + * \todo add support for src_only and dst_only + */ +void DetectGeoipRegister(void) +{ + sigmatch_table[DETECT_GEOIP].name = "geoip"; + sigmatch_table[DETECT_GEOIP].Match = DetectGeoipMatch; + sigmatch_table[DETECT_GEOIP].Setup = DetectGeoipSetup; + sigmatch_table[DETECT_GEOIP].Free = DetectGeoipDataFree; + sigmatch_table[DETECT_GEOIP].RegisterTests = DetectGeoipRegisterTests; +} + +/** + * \internal + * \brief This function is used to initialize the geolocation MaxMind engine + * + * \retval NULL if the engine couldn't be initialized + * \retval (GeoIP *) to the geolocation engine + */ +static GeoIP *InitGeolocationEngine(void) +{ + return GeoIP_new(GEOIP_MEMORY_CACHE); +} + +/** + * \internal + * \brief This function is used to geolocate the IP using the MaxMind libraries + * + * \param ip IP to geolocate (uint32_t ip) + * + * \retval NULL if it couldn't be geolocated + * \retval ptr (const char *) to the country code string + */ +static const char *GeolocateIPv4(GeoIP *geoengine, uint32_t ip) +{ + if (geoengine != NULL) + return GeoIP_country_code_by_ipnum(geoengine, ntohl(ip)); + return NULL; +} + +/* Match-on conditions supported */ +#define GEOIP_MATCH_SRC_STR "src" +#define GEOIP_MATCH_DST_STR "dst" +#define GEOIP_MATCH_BOTH_STR "both" +#define GEOIP_MATCH_ANY_STR "any" + +#define GEOIP_MATCH_NO_FLAG 0 +#define GEOIP_MATCH_SRC_FLAG 1 +#define GEOIP_MATCH_DST_FLAG 2 +#define GEOIP_MATCH_ANY_FLAG 3 /* default src and dst*/ +#define GEOIP_MATCH_BOTH_FLAG 4 +#define GEOIP_MATCH_NEGATED 8 + +/** + * \internal + * \brief This function is used to geolocate the IP using the MaxMind libraries + * + * \param ip IP to geolocate (uint32_t ip) + * + * \retval 0 no match + * \retval 1 match + */ +static int CheckGeoMatchIPv4(DetectGeoipData *geoipdata, uint32_t ip) +{ + const char *country; + int i; + country = GeolocateIPv4(geoipdata->geoengine, ip); + /* Check if NOT NEGATED match-on condition */ + if ((geoipdata->flags & GEOIP_MATCH_NEGATED) == 0) + { + for (i = 0; i < geoipdata->nlocations; i++) + if (country != NULL && strcmp(country, (char *)geoipdata->location[i])==0) + return 1; + } else { + /* Check if NEGATED match-on condition */ + for (i = 0; i < geoipdata->nlocations; i++) + if (country != NULL && strcmp(country, (char *)geoipdata->location[i])==0) + return 0; /* if one matches, rule does NOT match (negated) */ + return 1; /* returns 1 if no location matches (negated) */ + } + return 0; +} + +/** + * \internal + * \brief This function is used to match packets with a IPs in an specified country + * + * \param t pointer to thread vars + * \param det_ctx pointer to the pattern matcher thread + * \param p pointer to the current packet + * \param m pointer to the sigmatch that we will cast into DetectGeoipData + * + * \retval 0 no match + * \retval 1 match + */ +static int DetectGeoipMatch(ThreadVars *t, DetectEngineThreadCtx *det_ctx, + Packet *p, Signature *s, SigMatch *m) +{ + DetectGeoipData *geoipdata = (DetectGeoipData *)m->ctx; + int matches = 0; + + if (PKT_IS_IPV4(p)) + { + if (geoipdata->flags & ( GEOIP_MATCH_SRC_FLAG | GEOIP_MATCH_BOTH_FLAG )) + { + if (CheckGeoMatchIPv4(geoipdata, GET_IPV4_SRC_ADDR_U32(p))) + { + if (geoipdata->flags & GEOIP_MATCH_BOTH_FLAG) + matches++; + else + return 1; + } + } + if (geoipdata->flags & ( GEOIP_MATCH_DST_FLAG | GEOIP_MATCH_BOTH_FLAG )) + { + if (CheckGeoMatchIPv4(geoipdata, GET_IPV4_DST_ADDR_U32(p))) + { + if (geoipdata->flags & GEOIP_MATCH_BOTH_FLAG) + matches++; + else + return 1; + } + } + /* if matches == 2 is because match-on is "both" */ + if (matches == 2) + return 1; + } + + return 0; +} + +/** + * \brief This function is used to parse geoipdata + * + * \param str Pointer to the geoipdata value string + * + * \retval pointer to DetectGeoipData on success + * \retval NULL on failure + */ +static DetectGeoipData *DetectGeoipDataParse (char *str) +{ + DetectGeoipData *geoipdata = NULL; + uint16_t pos = 0; + uint16_t prevpos = 0; + uint16_t slen = 0; + int skiplocationparsing = 0; + + slen = strlen(str); + if (slen == 0) + goto error; + + /* We have a correct geoip options string */ + geoipdata = SCMalloc(sizeof(DetectGeoipData)); + if (unlikely(geoipdata == NULL)) + goto error; + + memset(geoipdata, 0x00, sizeof(DetectGeoipData)); + + /* Parse the geoip option string */ + while (pos <= slen) + { + /* search for ',' or end of string */ + if (str[pos] == ',' || pos == slen) + { + if (geoipdata->flags == GEOIP_MATCH_NO_FLAG) + { + /* Parse match-on condition */ + if (pos == slen) /* if end of option str then there are no match-on cond. */ + { + /* There was NO match-on condition! we default to ANY*/ + skiplocationparsing = 0; + geoipdata->flags |= GEOIP_MATCH_ANY_FLAG; + } else { + skiplocationparsing = 1; + if (strncmp(&str[prevpos], GEOIP_MATCH_SRC_STR, pos-prevpos) == 0) + geoipdata->flags |= GEOIP_MATCH_SRC_FLAG; + else if (strncmp(&str[prevpos], GEOIP_MATCH_DST_STR, pos-prevpos) == 0) + geoipdata->flags |= GEOIP_MATCH_DST_FLAG; + else if (strncmp(&str[prevpos], GEOIP_MATCH_BOTH_STR, pos-prevpos) == 0) + geoipdata->flags |= GEOIP_MATCH_BOTH_FLAG; + else if (strncmp(&str[prevpos], GEOIP_MATCH_ANY_STR, pos-prevpos) == 0) + geoipdata->flags |= GEOIP_MATCH_ANY_FLAG; + else { + /* There was NO match-on condition! we default to ANY*/ + skiplocationparsing = 0; + geoipdata->flags |= GEOIP_MATCH_ANY_FLAG; + } + } + } + if (geoipdata->flags != GEOIP_MATCH_NO_FLAG && skiplocationparsing == 0) + { + /* Parse location string: for now just the country code(s) */ + if (str[prevpos] == '!') + { + geoipdata->flags |= GEOIP_MATCH_NEGATED; + prevpos++; /* dot not copy the ! */ + } + if (pos-prevpos > GEOOPTION_MAXSIZE) + strlcpy((char *)geoipdata->location[geoipdata->nlocations], &str[prevpos], + GEOOPTION_MAXSIZE); + else + strlcpy((char *)geoipdata->location[geoipdata->nlocations], &str[prevpos], + pos-prevpos+1); + + if (geoipdata->nlocations < GEOOPTION_MAXLOCATIONS) + geoipdata->nlocations++; + } + prevpos = pos+1; + skiplocationparsing = 0; /* match-on condition for sure has been parsed already */ + } + pos++; + } + + SCLogDebug("GeoIP: %"PRIu32" countries loaded", geoipdata->nlocations); + for (int i=0; inlocations; i++) + SCLogDebug("GeoIP country code: %s", geoipdata->location[i]); + + SCLogDebug("flags %02X", geoipdata->flags); + if (geoipdata->flags & GEOIP_MATCH_NEGATED) { + SCLogDebug("negated geoip"); + } + + /* Initialize the geolocation engine */ + geoipdata->geoengine = InitGeolocationEngine(); + if (geoipdata==NULL) + goto error; + + return geoipdata; + +error: + if (geoipdata != NULL) + DetectGeoipDataFree(geoipdata); + return NULL; +} + +/** + * \internal + * \brief this function is used to add the geoip option into the signature + * + * \param de_ctx pointer to the Detection Engine Context + * \param s pointer to the Current Signature + * \param optstr pointer to the user provided options + * + * \retval 0 on Success + * \retval -1 on Failure + */ +static int DetectGeoipSetup(DetectEngineCtx *de_ctx, Signature *s, char *optstr) +{ + DetectGeoipData *geoipdata = NULL; + SigMatch *sm = NULL; + + geoipdata = DetectGeoipDataParse(optstr); + if (geoipdata == NULL) + goto error; + + /* Get this into a SigMatch and put it in the Signature. */ + sm = SigMatchAlloc(); + if (sm == NULL) + goto error; + + sm->type = DETECT_GEOIP; + sm->ctx = (void *)geoipdata; + + SigMatchAppendSMToList(s, sm, DETECT_SM_LIST_MATCH); + s->flags |= SIG_FLAG_REQUIRE_PACKET; + + return 0; + +error: + if (geoipdata != NULL) + DetectGeoipDataFree(geoipdata); + if (sm != NULL) + SCFree(sm); + return -1; + +} + +/** + * \brief this function will free memory associated with DetectGeoipData + * + * \param geoipdata pointer to DetectGeoipData + */ +static void DetectGeoipDataFree(void *ptr) { + if (ptr != NULL) { + DetectGeoipData *geoipdata = (DetectGeoipData *)ptr; + SCFree(geoipdata); + } +} + +#ifdef UNITTESTS + +static int GeoipParseTest(char *rule, int ncountries, char **countries, uint32_t flags) { + DetectEngineCtx *de_ctx = NULL; + int result = 0; + Signature *s = NULL; + DetectGeoipData *data = NULL; + + de_ctx = DetectEngineCtxInit(); + if (de_ctx == NULL) + goto end; + + de_ctx->flags |= DE_QUIET; + de_ctx->sig_list = SigInit(de_ctx, rule); + + if (de_ctx->sig_list == NULL) { + printf("sig parse failed: "); + goto end; + } + + s = de_ctx->sig_list; + if (s->sm_lists_tail[DETECT_SM_LIST_MATCH] == NULL) { + printf("empty server body list: "); + goto end; + } + + if (s->sm_lists_tail[DETECT_SM_LIST_MATCH]->type != DETECT_GEOIP) { + printf("last sm not geoip: "); + goto end; + } + + data = (DetectGeoipData *)s->sm_lists_tail[DETECT_SM_LIST_MATCH]->ctx; + if (data->flags != flags) { + printf("flags not right: (flags=%d)",data->flags); + goto end; + } + + if (data->nlocations!=ncountries) + { + printf("wrong number of parsed countries: "); + goto end; + } + + for (int i=0; ilocation[i],countries[i])!=0) + { + printf("wrong parsed country code: "); + goto end; + } + } + + result = 1; +end: + SigGroupCleanup(de_ctx); + SigCleanSignatures(de_ctx); + DetectEngineCtxFree(de_ctx); + + return result; +} + +static int GeoipParseTest01(void) { + char *ccodes[1] = {"US"}; + return GeoipParseTest("alert tcp any any -> any any (geoip:US;sid:1;)", 1, ccodes, + GEOIP_MATCH_ANY_FLAG); +} + +static int GeoipParseTest02(void) { + char *ccodes[1] = {"US"}; + return GeoipParseTest("alert tcp any any -> any any (geoip:!US;sid:1;)", 1, ccodes, + GEOIP_MATCH_ANY_FLAG | GEOIP_MATCH_NEGATED); +} + +static int GeoipParseTest03(void) { + char *ccodes[1] = {"US"}; + return GeoipParseTest("alert tcp any any -> any any (geoip:!US;sid:1;)", 1, ccodes, + GEOIP_MATCH_ANY_FLAG | GEOIP_MATCH_NEGATED); +} + +static int GeoipParseTest04(void) { + char *ccodes[1] = {"US"}; + return GeoipParseTest("alert tcp any any -> any any (geoip:src,US;sid:1;)", 1, ccodes, + GEOIP_MATCH_SRC_FLAG); +} + +static int GeoipParseTest05(void) { + char *ccodes[1] = {"US"}; + return GeoipParseTest("alert tcp any any -> any any (geoip:dst,!US;sid:1;)", 1, ccodes, + GEOIP_MATCH_DST_FLAG | GEOIP_MATCH_NEGATED); +} + +static int GeoipParseTest06(void) { + char *ccodes[3] = {"US", "ES", "UK"}; + return GeoipParseTest("alert tcp any any -> any any (geoip:US,ES,UK;sid:1;)", 3, ccodes, + GEOIP_MATCH_ANY_FLAG); +} + +static int GeoipParseTest07(void) { + char *ccodes[3] = {"US", "ES", "UK"}; + return GeoipParseTest("alert tcp any any -> any any (geoip:both,!US,ES,UK;sid:1;)", 3, ccodes, + GEOIP_MATCH_BOTH_FLAG | GEOIP_MATCH_NEGATED); +} + +/** + * \internal + * \brief This test tests geoip success and failure. + */ +static int GeoipMatchTest(char *rule, char *srcip, char *dstip) +{ + uint8_t *buf = (uint8_t *) "GET / HTTP/1.0\r\n\r\n"; + uint16_t buflen = strlen((char *)buf); + Packet *p1 = NULL; + ThreadVars th_v; + DetectEngineThreadCtx *det_ctx; + int result = 0; + + memset(&th_v, 0, sizeof(th_v)); + + p1 = UTHBuildPacketSrcDst(buf, buflen, IPPROTO_TCP, srcip, dstip); + + DetectEngineCtx *de_ctx = DetectEngineCtxInit(); + if (de_ctx == NULL) { + goto end; + } + + de_ctx->flags |= DE_QUIET; + + de_ctx->sig_list = SigInit(de_ctx, rule); + + if (de_ctx->sig_list == NULL) { + goto end; + } + + SigGroupBuild(de_ctx); + DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx); + + result = 2; + + SigMatchSignatures(&th_v, de_ctx, det_ctx, p1); + if (PacketAlertCheck(p1, 1) == 0) { + goto cleanup; + } + + result = 1; + +cleanup: + SigGroupCleanup(de_ctx); + SigCleanSignatures(de_ctx); + + DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx); + DetectEngineCtxFree(de_ctx); + +end: + return result; +} + +static int GeoipMatchTest01(void) { + /* Tests with IP of google DNS as US for both src and dst IPs */ + return GeoipMatchTest("alert tcp any any -> any any (geoip:US;sid:1;)", "8.8.8.8", "8.8.8.8"); + /* Expected result 1 = match */ +} + +static int GeoipMatchTest02(void) { + /* Tests with IP of google DNS as US, and m.root-servers.net as japan */ + return GeoipMatchTest("alert tcp any any -> any any (geoip:JP;sid:1;)", "8.8.8.8", + "202.12.27.33"); + /* Expected result 1 = match */ +} + +static int GeoipMatchTest03(void) { + /* Tests with IP of google DNS as US, and m.root-servers.net as japan */ + return GeoipMatchTest("alert tcp any any -> any any (geoip:dst,JP;sid:1;)", + "8.8.8.8", "202.12.27.33"); + /* Expected result 1 = match */ +} + +static int GeoipMatchTest04(void) { + /* Tests with IP of google DNS as US, and m.root-servers.net as japan */ + return GeoipMatchTest("alert tcp any any -> any any (geoip:src,JP;sid:1;)", + "8.8.8.8", "202.12.27.33"); + /* Expected result 2 = NO match */ +} + +static int GeoipMatchTest05(void) { + /* Tests with IP of google DNS as US, and m.root-servers.net as japan */ + return GeoipMatchTest("alert tcp any any -> any any (geoip:src,JP,US;sid:1;)", + "8.8.8.8", "202.12.27.33"); + /* Expected result 1 = match */ +} + +static int GeoipMatchTest06(void) { + /* Tests with IP of google DNS as US, and m.root-servers.net as japan */ + return GeoipMatchTest("alert tcp any any -> any any (geoip:src,ES,JP,US,UK,PT;sid:1;)", + "8.8.8.8", "202.12.27.33"); + /* Expected result 1 = match */ +} + +static int GeoipMatchTest07(void) { + /* Tests with IP of google DNS as US, and m.root-servers.net as japan */ + return GeoipMatchTest("alert tcp any any -> any any (geoip:src,!ES,JP,US,UK,PT;sid:1;)", + "8.8.8.8", "202.12.27.33"); + /* Expected result 2 = NO match */ +} + + +#endif /* UNITTESTS */ + +/** + * \internal + * \brief This function registers unit tests for DetectGeoip + */ +static void DetectGeoipRegisterTests(void) +{ +#ifdef UNITTESTS + UtRegisterTest("GeoipParseTest01", GeoipParseTest01, 1); + UtRegisterTest("GeoipParseTest02", GeoipParseTest02, 1); + UtRegisterTest("GeoipParseTest03", GeoipParseTest03, 1); + UtRegisterTest("GeoipParseTest04", GeoipParseTest04, 1); + UtRegisterTest("GeoipParseTest05", GeoipParseTest05, 1); + UtRegisterTest("GeoipParseTest06", GeoipParseTest06, 1); + UtRegisterTest("GeoipParseTest07", GeoipParseTest07, 1); + + UtRegisterTest("GeoipMatchTest01", GeoipMatchTest01, 1); + UtRegisterTest("GeoipMatchTest02", GeoipMatchTest02, 1); + UtRegisterTest("GeoipMatchTest03", GeoipMatchTest03, 1); + UtRegisterTest("GeoipMatchTest04", GeoipMatchTest04, 2); + UtRegisterTest("GeoipMatchTest05", GeoipMatchTest05, 1); + UtRegisterTest("GeoipMatchTest06", GeoipMatchTest06, 1); + UtRegisterTest("GeoipMatchTest07", GeoipMatchTest07, 2); +#endif /* UNITTESTS */ +} + +#endif /* HAVE_GEOIP */ diff --git a/src/detect-geoip.h b/src/detect-geoip.h new file mode 100644 index 0000000000..1bfc7aff0d --- /dev/null +++ b/src/detect-geoip.h @@ -0,0 +1,46 @@ +/* Copyright (C) 2012 Open Information Security Foundation + * + * You can copy, redistribute or modify this Program under the terms of + * the GNU General Public License version 2 as published by the Free + * Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * version 2 along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +/** + * \file + * + * \author Ignacio Sanchez + */ + +#ifndef __DETECT_GEOIP_H__ +#define __DETECT_GEOIP_H__ + +#ifdef HAVE_GEOIP + +#include +#include "util-spm-bm.h" + +#define GEOOPTION_MAXSIZE 3 /* Country Code (2 chars) + NULL */ +#define GEOOPTION_MAXLOCATIONS 64 + +typedef struct DetectGeoipData_ { + uint8_t location[GEOOPTION_MAXLOCATIONS][GEOOPTION_MAXSIZE]; /** country code for now, null term.*/ + int nlocations; /** number of location strings parsed */ + uint32_t flags; + GeoIP *geoengine; +} DetectGeoipData; + +#endif + +void DetectGeoipRegister(void); + +#endif diff --git a/src/detect.c b/src/detect.c index 4aafca3427..c02a27a5fe 100644 --- a/src/detect.c +++ b/src/detect.c @@ -144,6 +144,7 @@ #include "detect-app-layer-event.h" #include "detect-luajit.h" #include "detect-iprep.h" +#include "detect-geoip.h" #include "util-rule-vars.h" @@ -4714,6 +4715,7 @@ void SigTableSetup(void) { DetectBytetestRegister(); DetectBytejumpRegister(); DetectSameipRegister(); + DetectGeoipRegister(); DetectL3ProtoRegister(); DetectIPProtoRegister(); DetectWithinRegister(); diff --git a/src/detect.h b/src/detect.h index 3ebcb8a87d..c4669488f2 100644 --- a/src/detect.h +++ b/src/detect.h @@ -1012,6 +1012,7 @@ enum { DETECT_BYTETEST, DETECT_BYTEJUMP, DETECT_SAMEIP, + DETECT_GEOIP, DETECT_IPPROTO, DETECT_FLOW, DETECT_WINDOW, diff --git a/src/util-error.c b/src/util-error.c index 485e0988e4..6192892f00 100644 --- a/src/util-error.c +++ b/src/util-error.c @@ -239,6 +239,8 @@ const char * SCErrorToString(SCError err) CASE_CODE (SC_ERR_EVENT_ENGINE); CASE_CODE (SC_ERR_NO_LUAJIT_SUPPORT); CASE_CODE (SC_ERR_LUAJIT_ERROR); + CASE_CODE (SC_ERR_NO_GEOIP_SUPPORT); + CASE_CODE (SC_ERR_GEOIP_ERROR); CASE_CODE (SC_ERR_DEFRAG_INIT); CASE_CODE (SC_ERR_NO_REPUTATION); CASE_CODE (SC_ERR_NOT_SUPPORTED); diff --git a/src/util-error.h b/src/util-error.h index ad30cee42a..2f823246ae 100644 --- a/src/util-error.h +++ b/src/util-error.h @@ -256,6 +256,8 @@ typedef enum { SC_ERR_NO_REPUTATION, SC_ERR_NOT_SUPPORTED, SC_ERR_IPFW_SETSOCKOPT, + SC_ERR_NO_GEOIP_SUPPORT, + SC_ERR_GEOIP_ERROR, } SCError; const char *SCErrorToString(SCError);