/* Proto part of the detection engine. * * Copyright (c) 2008 Victor Julien * * TODO move this out of the detection plugin structure */ #include "eidps-common.h" #include "decode.h" #include "detect.h" #include "flow-var.h" #include "util-cidr.h" #include "util-byte.h" #include "util-unittest.h" #include "detect-engine-siggroup.h" int DetectProtoSetup (DetectEngineCtx *de_ctx, Signature *s, SigMatch *m, char *sidstr); void DetectProtoTests (void); void DetectProtoRegister (void) { sigmatch_table[DETECT_PROTO].name = "__proto__"; sigmatch_table[DETECT_PROTO].Match = NULL; sigmatch_table[DETECT_PROTO].Setup = DetectProtoSetup; sigmatch_table[DETECT_PROTO].Free = NULL; sigmatch_table[DETECT_PROTO].RegisterTests = DetectProtoTests; } DetectProto *DetectProtoInit(void) { DetectProto *dp = malloc(sizeof(DetectProto)); if (dp == NULL) { return NULL; } memset(dp,0,sizeof(DetectProto)); return dp; } /** * \brief Free a DetectAddressGroup object * * \param dp Pointer to the DetectProto instance to be freed */ void DetectProtoFree(DetectProto *dp) { if (dp == NULL) return; free(dp); } /** * \brief Parses a protocol sent as a string. * * \param dp Pointer to the DetectProto instance which will be updated with the * incoming protocol information. * \param str Pointer to the string containing the protocol name. * * \retval 0 Always return 0. */ int DetectProtoParse(DetectProto *dp, char *str) { int proto; if (strcasecmp(str, "tcp") == 0) { proto = IPPROTO_TCP; dp->proto[proto / 8] |= 1 << (proto % 8); } else if (strcasecmp(str, "udp") == 0) { proto = IPPROTO_UDP; dp->proto[proto / 8] |= 1 << (proto % 8); } else if (strcasecmp(str, "icmp") == 0) { proto = IPPROTO_ICMP; dp->proto[proto / 8] |= 1 << (proto % 8); } else if (strcasecmp(str,"ip") == 0) { /* Proto "ip" is treated as an "any" */ dp->flags |= DETECT_PROTO_ANY; memset(dp->proto, 0xff, sizeof(dp->proto)); } else { uint8_t proto_u8; /* Used to avoid sign extension */ /* Extract out a 0-256 value with validation checks */ if (ByteExtractStringUint8(&proto_u8, 10, 0, str) == -1) { // XXX goto error; } proto = (int)proto_u8; /* Proto 0 is the same as "ip" above */ if (proto == IPPROTO_IP) { dp->flags |= DETECT_PROTO_ANY; } else { dp->proto[proto / 8] |= 1<<(proto % 8); } } return 0; error: return -1; } /* XXX remove */ int DetectProtoSetup (DetectEngineCtx *de_ctx, Signature *s, SigMatch *m, char *str) { return 0; } /* TESTS */ #ifdef UNITTESTS static int ProtoTestParse01 (void) { DetectProto dp; memset(&dp,0,sizeof(DetectProto)); int r = DetectProtoParse(&dp, "6"); if (r == 0) { return 1; } return 0; } static int ProtoTestParse02 (void) { DetectProto dp; memset(&dp,0,sizeof(DetectProto)); int r = DetectProtoParse(&dp, "tcp"); if (r == 0 && dp.proto[(IPPROTO_TCP/8)] & (1<<(IPPROTO_TCP%8))) { return 1; } return 0; } static int ProtoTestParse03 (void) { DetectProto dp; memset(&dp,0,sizeof(DetectProto)); int r = DetectProtoParse(&dp, "ip"); if (r == 0 && dp.flags & DETECT_PROTO_ANY) { return 1; } return 0; } static int ProtoTestParse04 (void) { DetectProto dp; memset(&dp,0,sizeof(DetectProto)); /* Check for a bad number */ int r = DetectProtoParse(&dp, "4242"); if (r == -1) { return 1; } return 0; } #endif /* UNITTESTS */ void DetectProtoTests(void) { #ifdef UNITTESTS UtRegisterTest("ProtoTestParse01", ProtoTestParse01, 1); UtRegisterTest("ProtoTestParse02", ProtoTestParse02, 1); UtRegisterTest("ProtoTestParse03", ProtoTestParse03, 1); UtRegisterTest("ProtoTestParse04", ProtoTestParse04, 1); #endif /* UNITTESTS */ }