void FlowVarPrint(GenericVar *gv) { uint16_t u; if (!SCLogDebugEnabled()) return; if (gv == NULL) return; if (gv->type == DETECT_FLOWVAR || gv->type == DETECT_FLOWINT) { FlowVar *fv = (FlowVar *)gv; if (fv->datatype == FLOWVAR_TYPE_STR) { SCLogDebug("Name idx \"%" PRIu16 "\", Value \"", fv->idx); for (u = 0; u < fv->data.fv_str.value_len; u++) { if (isprint(fv->data.fv_str.value[u])) SCLogDebug("%c", fv->data.fv_str.value[u]); else SCLogDebug("\\%02X", fv->data.fv_str.value[u]); } SCLogDebug("\", Len \"%" PRIu16 "\"\n", fv->data.fv_str.value_len); } else if (fv->datatype == FLOWVAR_TYPE_INT) { SCLogDebug("Name idx \"%" PRIu16 "\", Value \"%" PRIu32 "\"", fv->idx, fv->data.fv_int.value); } else { SCLogDebug("Unknown data type at flowvars\n"); } } FlowVarPrint(gv->next); }
/** * \brief match the specified filemagic * * \param t thread local vars * \param det_ctx pattern matcher thread local data * \param f *LOCKED* flow * \param flags direction flags * \param file file being inspected * \param s signature being inspected * \param m sigmatch that we will cast into DetectFilemagicData * * \retval 0 no match * \retval 1 match */ static int DetectFilemagicMatch (ThreadVars *t, DetectEngineThreadCtx *det_ctx, Flow *f, uint8_t flags, File *file, Signature *s, SigMatch *m) { SCEnter(); int ret = 0; DetectFilemagicData *filemagic = (DetectFilemagicData *)m->ctx; if (file->txid < det_ctx->tx_id) SCReturnInt(0); if (file->txid > det_ctx->tx_id) SCReturnInt(0); DetectFilemagicThreadData *tfilemagic = (DetectFilemagicThreadData *)DetectThreadCtxGetKeywordThreadCtx(det_ctx, filemagic->thread_ctx_id); if (tfilemagic == NULL) { SCReturnInt(0); } if (file->magic == NULL) { FilemagicThreadLookup(&tfilemagic->ctx, file); } if (file->magic != NULL) { SCLogDebug("magic %s", file->magic); /* we include the \0 in the inspection, so patterns can match on the * end of the string. */ if (BoyerMooreNocase(filemagic->name, filemagic->len, (uint8_t *)file->magic, strlen(file->magic) + 1, filemagic->bm_ctx) != NULL) { #ifdef DEBUG if (SCLogDebugEnabled()) { char *name = SCMalloc(filemagic->len + 1); if (name != NULL) { memcpy(name, filemagic->name, filemagic->len); name[filemagic->len] = '\0'; SCLogDebug("will look for filemagic %s", name); } } #endif if (!(filemagic->flags & DETECT_CONTENT_NEGATED)) { ret = 1; } } else if (filemagic->flags & DETECT_CONTENT_NEGATED) { SCLogDebug("negated match"); ret = 1; } } SCReturnInt(ret); }
/** * \brief This function is used to parse fileet * * \param str Pointer to the fileext value string * * \retval pointer to DetectFileextData on success * \retval NULL on failure */ static DetectFileextData *DetectFileextParse (const char *str, bool negate) { DetectFileextData *fileext = NULL; /* We have a correct filename option */ fileext = SCMalloc(sizeof(DetectFileextData)); if (unlikely(fileext == NULL)) goto error; memset(fileext, 0x00, sizeof(DetectFileextData)); if (DetectContentDataParse("fileext", str, &fileext->ext, &fileext->len) == -1) { goto error; } uint16_t u; for (u = 0; u < fileext->len; u++) fileext->ext[u] = tolower(fileext->ext[u]); if (negate) { fileext->flags |= DETECT_CONTENT_NEGATED; } SCLogDebug("flags %02X", fileext->flags); if (fileext->flags & DETECT_CONTENT_NEGATED) { SCLogDebug("negated fileext"); } #ifdef DEBUG if (SCLogDebugEnabled()) { char *ext = SCMalloc(fileext->len + 1); if (ext != NULL) { memcpy(ext, fileext->ext, fileext->len); ext[fileext->len] = '\0'; SCLogDebug("will look for fileext %s", ext); } } #endif return fileext; error: if (fileext != NULL) DetectFileextFree(fileext); return NULL; }
/** * \brief match the specified filename * * \param t thread local vars * \param det_ctx pattern matcher thread local data * \param f *LOCKED* flow * \param flags direction flags * \param file file being inspected * \param s signature being inspected * \param m sigmatch that we will cast into DetectFilenameData * * \retval 0 no match * \retval 1 match */ static int DetectFilenameMatch (ThreadVars *t, DetectEngineThreadCtx *det_ctx, Flow *f, uint8_t flags, File *file, Signature *s, SigMatch *m) { SCEnter(); int ret = 0; DetectFilenameData *filename = m->ctx; if (file->name == NULL) SCReturnInt(0); if (file->txid < det_ctx->tx_id) SCReturnInt(0); if (file->txid > det_ctx->tx_id) SCReturnInt(0); if (BoyerMooreNocase(filename->name, filename->len, file->name, file->name_len, filename->bm_ctx->bmGs, filename->bm_ctx->bmBc) != NULL) { #ifdef DEBUG if (SCLogDebugEnabled()) { char *name = SCMalloc(filename->len + 1); if (name != NULL) { memcpy(name, filename->name, filename->len); name[filename->len] = '\0'; SCLogDebug("will look for filename %s", name); } } #endif if (!(filename->flags & DETECT_CONTENT_NEGATED)) { ret = 1; } } if (ret == 0 && (filename->flags & DETECT_CONTENT_NEGATED)) { SCLogDebug("negated match"); ret = 1; } SCReturnInt(ret); }
/** * \brief Parse the filename keyword * * \param idstr Pointer to the user provided option * * \retval filename pointer to DetectFilenameData on success * \retval NULL on failure */ static DetectFilenameData *DetectFilenameParse (char *str) { DetectFilenameData *filename = NULL; /* We have a correct filename option */ filename = SCMalloc(sizeof(DetectFilenameData)); if (unlikely(filename == NULL)) goto error; memset(filename, 0x00, sizeof(DetectFilenameData)); if (DetectParseContentString (str, &filename->name, &filename->len, &filename->flags) == -1) { goto error; } filename->bm_ctx = BoyerMooreCtxInit(filename->name, filename->len); if (filename->bm_ctx == NULL) { goto error; } SCLogDebug("flags %02X", filename->flags); if (filename->flags & DETECT_CONTENT_NEGATED) { SCLogDebug("negated filename"); } BoyerMooreCtxToNocase(filename->bm_ctx, filename->name, filename->len); #ifdef DEBUG if (SCLogDebugEnabled()) { char *name = SCMalloc(filename->len + 1); if (name != NULL) { memcpy(name, filename->name, filename->len); name[filename->len] = '\0'; SCLogDebug("will look for filename %s", name); } } #endif return filename; error: if (filename != NULL) DetectFilenameFree(filename); return NULL; }
/** * \brief Print the information and chunks of a Body * \param body pointer to the HtpBody holding the list * \retval none */ void HtpBodyPrint(HtpBody *body) { if (SCLogDebugEnabled()||1) { SCEnter(); if (body->first == NULL) return; HtpBodyChunk *cur = NULL; SCLogDebug("--- Start body chunks at %p ---", body); printf("--- Start body chunks at %p ---\n", body); for (cur = body->first; cur != NULL; cur = cur->next) { SCLogDebug("Body %p; data %p, len %"PRIu32, body, cur->data, (uint32_t)cur->len); printf("Body %p; data %p, len %"PRIu32"\n", body, cur->data, (uint32_t)cur->len); PrintRawDataFp(stdout, (uint8_t*)cur->data, cur->len); } SCLogDebug("--- End body chunks at %p ---", body); } }
/** * \brief Print the information and chunks of a Body * \param body pointer to the HtpBody holding the list * \retval none */ void HtpBodyPrint(HtpBody *body) { if (SCLogDebugEnabled()||1) { SCEnter(); if (body->first == NULL) return; HtpBodyChunk *cur = NULL; SCLogDebug("--- Start body chunks at %p ---", body); printf("--- Start body chunks at %p ---\n", body); for (cur = body->first; cur != NULL; cur = cur->next) { const uint8_t *data = NULL; uint32_t data_len = 0; StreamingBufferSegmentGetData(body->sb, &cur->sbseg, &data, &data_len); SCLogDebug("Body %p; data %p, len %"PRIu32, body, data, data_len); printf("Body %p; data %p, len %"PRIu32"\n", body, data, data_len); PrintRawDataFp(stdout, data, data_len); } SCLogDebug("--- End body chunks at %p ---", body); } }
void DecodeIPV6(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, uint8_t *pkt, uint16_t len, PacketQueue *pq) { int ret; SCPerfCounterIncr(dtv->counter_ipv6, tv->sc_perf_pca); /* do the actual decoding */ ret = DecodeIPV6Packet (tv, dtv, p, pkt, len); if (ret < 0) { p->ip6h = NULL; return; } #ifdef DEBUG if (SCLogDebugEnabled()) { /* only convert the addresses if debug is really enabled */ /* debug print */ char s[46], d[46]; PrintInet(AF_INET6, (const void *)GET_IPV6_SRC_ADDR(p), s, sizeof(s)); PrintInet(AF_INET6, (const void *)GET_IPV6_DST_ADDR(p), d, sizeof(d)); SCLogDebug("IPV6 %s->%s - CLASS: %" PRIu32 " FLOW: %" PRIu32 " NH: %" PRIu32 " PLEN: %" PRIu32 " HLIM: %" PRIu32 "", s,d, IPV6_GET_CLASS(p), IPV6_GET_FLOW(p), IPV6_GET_NH(p), IPV6_GET_PLEN(p), IPV6_GET_HLIM(p)); } #endif /* DEBUG */ /* now process the Ext headers and/or the L4 Layer */ switch(IPV6_GET_NH(p)) { case IPPROTO_TCP: IPV6_SET_L4PROTO (p, IPPROTO_TCP); return DecodeTCP(tv, dtv, p, pkt + IPV6_HEADER_LEN, IPV6_GET_PLEN(p), pq); case IPPROTO_UDP: IPV6_SET_L4PROTO (p, IPPROTO_UDP); return DecodeUDP(tv, dtv, p, pkt + IPV6_HEADER_LEN, IPV6_GET_PLEN(p), pq); break; case IPPROTO_ICMPV6: IPV6_SET_L4PROTO (p, IPPROTO_ICMPV6); return DecodeICMPV6(tv, dtv, p, pkt + IPV6_HEADER_LEN, IPV6_GET_PLEN(p), pq); case IPPROTO_SCTP: IPV6_SET_L4PROTO (p, IPPROTO_SCTP); return DecodeSCTP(tv, dtv, p, pkt + IPV6_HEADER_LEN, IPV6_GET_PLEN(p), pq); case IPPROTO_IPIP: IPV6_SET_L4PROTO(p, IPPROTO_IPIP); return DecodeIPv4inIPv6(tv, dtv, p, pkt + IPV6_HEADER_LEN, IPV6_GET_PLEN(p), pq); case IPPROTO_IPV6: return DecodeIP6inIP6(tv, dtv, p, pkt + IPV6_HEADER_LEN, IPV6_GET_PLEN(p), pq); case IPPROTO_FRAGMENT: case IPPROTO_HOPOPTS: case IPPROTO_ROUTING: case IPPROTO_NONE: case IPPROTO_DSTOPTS: case IPPROTO_AH: case IPPROTO_ESP: DecodeIPV6ExtHdrs(tv, dtv, p, pkt + IPV6_HEADER_LEN, IPV6_GET_PLEN(p), pq); break; default: p->proto = IPV6_GET_NH(p); break; } /* Pass to defragger if a fragment. */ if (IPV6_EXTHDR_ISSET_FH(p)) { Packet *rp = Defrag(tv, dtv, NULL, p); if (rp != NULL) { DecodeIPV6(tv, dtv, rp, (uint8_t *)rp->ip6h, IPV6_GET_PLEN(rp) + IPV6_HEADER_LEN, pq); PacketEnqueue(pq, rp); /* Not really a tunnel packet, but we're piggybacking that * functionality for now. */ SET_TUNNEL_PKT(p); } } #ifdef DEBUG if (IPV6_EXTHDR_ISSET_FH(p)) { SCLogDebug("IPV6 FRAG - HDRLEN: %" PRIuMAX " NH: %" PRIu32 " OFFSET: %" PRIu32 " ID: %" PRIu32 "", (uintmax_t)IPV6_EXTHDR_GET_FH_HDRLEN(p), IPV6_EXTHDR_GET_FH_NH(p), IPV6_EXTHDR_GET_FH_OFFSET(p), IPV6_EXTHDR_GET_FH_ID(p)); } if (IPV6_EXTHDR_ISSET_RH(p)) { SCLogDebug("IPV6 ROUTE - HDRLEN: %" PRIu32 " NH: %" PRIu32 " TYPE: %" PRIu32 "", IPV6_EXTHDR_GET_RH_HDRLEN(p), IPV6_EXTHDR_GET_RH_NH(p), IPV6_EXTHDR_GET_RH_TYPE(p)); } if (IPV6_EXTHDR_ISSET_HH(p)) { SCLogDebug("IPV6 HOPOPT - HDRLEN: %" PRIu32 " NH: %" PRIu32 "", IPV6_EXTHDR_GET_HH_HDRLEN(p), IPV6_EXTHDR_GET_HH_NH(p)); } if (IPV6_EXTHDR_ISSET_DH1(p)) { SCLogDebug("IPV6 DSTOPT1 - HDRLEN: %" PRIu32 " NH: %" PRIu32 "", IPV6_EXTHDR_GET_DH1_HDRLEN(p), IPV6_EXTHDR_GET_DH1_NH(p)); } if (IPV6_EXTHDR_ISSET_DH2(p)) { SCLogDebug("IPV6 DSTOPT2 - HDRLEN: %" PRIu32 " NH: %" PRIu32 "", IPV6_EXTHDR_GET_DH2_HDRLEN(p), IPV6_EXTHDR_GET_DH2_NH(p)); } #endif return; }
static int DetectMsgSetup (DetectEngineCtx *de_ctx, Signature *s, char *msgstr) { char *str = NULL; uint16_t len; if (strlen(msgstr) == 0) goto error; /* strip "'s */ if (msgstr[0] == '\"' && msgstr[strlen(msgstr)-1] == '\"') { str = SCStrdup(msgstr+1); if (unlikely(str == NULL)) goto error; str[strlen(msgstr)-2] = '\0'; } else if (msgstr[1] == '\"' && msgstr[strlen(msgstr)-1] == '\"') { /* XXX do this parsing in a better way */ str = SCStrdup(msgstr+2); if (unlikely(str == NULL)) goto error; str[strlen(msgstr)-3] = '\0'; //printf("DetectMsgSetup: format hack applied: \'%s\'\n", str); } else { SCLogError(SC_ERR_INVALID_VALUE, "format error \'%s\'", msgstr); goto error; } len = strlen(str); if (len == 0) goto error; char converted = 0; { uint16_t i, x; uint8_t escape = 0; /* it doesn't matter if we need to escape or not we remove the extra "\" to mimic snort */ for (i = 0, x = 0; i < len; i++) { //printf("str[%02u]: %c\n", i, str[i]); if(!escape && str[i] == '\\') { escape = 1; } else if (escape) { if (str[i] != ':' && str[i] != ';' && str[i] != '\\' && str[i] != '\"') { SCLogDebug("character \"%c\" does not need to be escaped but is" ,str[i]); } escape = 0; converted = 1; str[x] = str[i]; x++; }else{ str[x] = str[i]; x++; } } #if 0 //def DEBUG if (SCLogDebugEnabled()) { for (i = 0; i < x; i++) { printf("%c", str[i]); } printf("\n"); } #endif if (converted) { len = x; str[len] = '\0'; } } s->msg = SCMalloc(len + 1); if (s->msg == NULL) goto error; strlcpy(s->msg, str, len + 1); SCFree(str); return 0; error: SCFree(str); return -1; }
int DetectBytejumpMatch(ThreadVars *t, DetectEngineThreadCtx *det_ctx, Packet *p, Signature *s, SigMatch *m) { DetectBytejumpData *data = (DetectBytejumpData *)m->ctx; uint8_t *ptr = NULL; uint8_t *jumpptr = NULL; uint16_t len = 0; uint64_t val = 0; int extbytes; if (p->payload_len == 0) { return 0; } /* Calculate the ptr value for the bytejump and length remaining in * the packet from that point. */ if (data->flags & DETECT_BYTEJUMP_RELATIVE) { ptr = p->payload + det_ctx->buffer_offset; len = p->payload_len - det_ctx->buffer_offset; /* No match if there is no relative base */ if (ptr == NULL || len == 0) { return 0; } ptr += data->offset; len -= data->offset; } else { ptr = p->payload + data->offset; len = p->payload_len - data->offset; } /* Verify the to-be-extracted data is within the packet */ if (ptr < p->payload || data->nbytes > len) { SCLogDebug("Data not within packet " "payload=%p, ptr=%p, len=%d, nbytes=%d", p->payload, ptr, len, data->nbytes); return 0; } /* Extract the byte data */ if (data->flags & DETECT_BYTEJUMP_STRING) { extbytes = ByteExtractStringUint64(&val, data->base, data->nbytes, (const char *)ptr); if(extbytes <= 0) { SCLogError(SC_ERR_BYTE_EXTRACT_FAILED,"Error extracting %d bytes " "of string data: %d", data->nbytes, extbytes); return -1; } } else { int endianness = (data->flags & DETECT_BYTEJUMP_LITTLE) ? BYTE_LITTLE_ENDIAN : BYTE_BIG_ENDIAN; extbytes = ByteExtractUint64(&val, endianness, data->nbytes, ptr); if (extbytes != data->nbytes) { SCLogError(SC_ERR_BYTE_EXTRACT_FAILED,"Error extracting %d bytes " "of numeric data: %d", data->nbytes, extbytes); return -1; } } //printf("VAL: (%" PRIu64 " x %" PRIu32 ") + %d + %" PRId32 "\n", val, data->multiplier, extbytes, data->post_offset); /* Adjust the jump value based on flags */ val *= data->multiplier; if (data->flags & DETECT_BYTEJUMP_ALIGN) { if ((val % 4) != 0) { val += 4 - (val % 4); } } val += data->post_offset; /* Calculate the jump location */ if (data->flags & DETECT_BYTEJUMP_BEGIN) { jumpptr = p->payload + val; //printf("NEWVAL: payload %p + %ld = %p\n", p->payload, val, jumpptr); } else { val += extbytes; jumpptr = ptr + val; //printf("NEWVAL: ptr %p + %ld = %p\n", ptr, val, jumpptr); } /* Validate that the jump location is still in the packet * \todo Should this validate it is still in the *payload*? */ if ((jumpptr < p->payload) || (jumpptr >= p->payload + p->payload_len)) { SCLogDebug("Jump location (%p) is not within " "packet (%p-%p)", jumpptr, p->payload, p->payload + p->payload_len - 1); return 0; } #ifdef DEBUG if (SCLogDebugEnabled()) { uint8_t *sptr = (data->flags & DETECT_BYTEJUMP_BEGIN) ? p->payload : ptr; SCLogDebug("jumping %" PRId64 " bytes from %p (%08x) to %p (%08x)", val, sptr, (int)(sptr - p->payload), jumpptr, (int)(jumpptr - p->payload)); } #endif /* DEBUG */ /* Adjust the detection context to the jump location. */ det_ctx->buffer_offset = jumpptr - p->payload; return 1; }
static int DetectFlowvarSetup (DetectEngineCtx *de_ctx, Signature *s, char *rawstr) { DetectFlowvarData *cd = NULL; SigMatch *sm = NULL; char *str = rawstr; char dubbed = 0; uint16_t len; char *varname = NULL, *varcontent = NULL; #define MAX_SUBSTRINGS 30 int ret = 0, res = 0; int ov[MAX_SUBSTRINGS]; ret = pcre_exec(parse_regex, parse_regex_study, rawstr, strlen(rawstr), 0, 0, ov, MAX_SUBSTRINGS); if (ret != 3) { SCLogError(SC_ERR_PCRE_MATCH, "\"%s\" is not a valid setting for flowvar.", rawstr); return -1; } const char *str_ptr; res = pcre_get_substring((char *)rawstr, ov, MAX_SUBSTRINGS, 1, &str_ptr); if (res < 0) { SCLogError(SC_ERR_PCRE_GET_SUBSTRING, "pcre_get_substring failed"); return -1; } varname = (char *)str_ptr; if (ret > 2) { res = pcre_get_substring((char *)rawstr, ov, MAX_SUBSTRINGS, 2, &str_ptr); if (res < 0) { SCLogError(SC_ERR_PCRE_GET_SUBSTRING, "pcre_get_substring failed"); return -1; } varcontent = (char *)str_ptr; } if (varcontent[0] == '\"' && varcontent[strlen(varcontent)-1] == '\"') { str = SCStrdup(varcontent+1); str[strlen(varcontent)-2] = '\0'; dubbed = 1; } len = strlen(str); if (len == 0) { if (dubbed) SCFree(str); return -1; } cd = SCMalloc(sizeof(DetectFlowvarData)); if (cd == NULL) goto error; char converted = 0; { uint16_t i, x; uint8_t bin = 0, binstr[3] = "", binpos = 0; for (i = 0, x = 0; i < len; i++) { // printf("str[%02u]: %c\n", i, str[i]); if (str[i] == '|') { if (bin) { bin = 0; } else { bin = 1; } } else { if (bin) { if (isdigit(str[i]) || str[i] == 'A' || str[i] == 'a' || str[i] == 'B' || str[i] == 'b' || str[i] == 'C' || str[i] == 'c' || str[i] == 'D' || str[i] == 'd' || str[i] == 'E' || str[i] == 'e' || str[i] == 'F' || str[i] == 'f') { // printf("part of binary: %c\n", str[i]); binstr[binpos] = (char)str[i]; binpos++; if (binpos == 2) { uint8_t c = strtol((char *)binstr, (char **) NULL, 16) & 0xFF; binpos = 0; str[x] = c; x++; converted = 1; } } else if (str[i] == ' ') { // printf("space as part of binary string\n"); } } else { str[x] = str[i]; x++; } } } #ifdef DEBUG if (SCLogDebugEnabled()) { for (i = 0; i < x; i++) { if (isprint(str[i])) printf("%c", str[i]); else printf("\\x%02u", str[i]); } printf("\n"); } #endif if (converted) len = x; } cd->content = SCMalloc(len); if (cd->content == NULL) { if (dubbed) SCFree(str); SCFree(cd); return -1; } cd->name = SCStrdup(varname); cd->idx = VariableNameGetIdx(varname,DETECT_FLOWVAR); memcpy(cd->content, str, len); cd->content_len = len; cd->flags = 0; /* Okay so far so good, lets get this into a SigMatch * and put it in the Signature. */ sm = SigMatchAlloc(); if (sm == NULL) goto error; sm->type = DETECT_FLOWVAR; sm->ctx = (void *)cd; SigMatchAppendPacket(s, sm); if (dubbed) SCFree(str); return 0; error: if (dubbed) SCFree(str); if (cd) SCFree(cd); if (sm) SCFree(sm); return -1; }
int DecodeIPV6(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, uint8_t *pkt, uint16_t len, PacketQueue *pq) { int ret; StatsIncr(tv, dtv->counter_ipv6); /* do the actual decoding */ ret = DecodeIPV6Packet (tv, dtv, p, pkt, len); if (unlikely(ret < 0)) { p->ip6h = NULL; return TM_ECODE_FAILED; } #ifdef DEBUG if (SCLogDebugEnabled()) { /* only convert the addresses if debug is really enabled */ /* debug print */ char s[46], d[46]; PrintInet(AF_INET6, (const void *)GET_IPV6_SRC_ADDR(p), s, sizeof(s)); PrintInet(AF_INET6, (const void *)GET_IPV6_DST_ADDR(p), d, sizeof(d)); SCLogDebug("IPV6 %s->%s - CLASS: %" PRIu32 " FLOW: %" PRIu32 " NH: %" PRIu32 " PLEN: %" PRIu32 " HLIM: %" PRIu32 "", s,d, IPV6_GET_CLASS(p), IPV6_GET_FLOW(p), IPV6_GET_NH(p), IPV6_GET_PLEN(p), IPV6_GET_HLIM(p)); } #endif /* DEBUG */ /* now process the Ext headers and/or the L4 Layer */ switch(IPV6_GET_NH(p)) { case IPPROTO_TCP: IPV6_SET_L4PROTO (p, IPPROTO_TCP); DecodeTCP(tv, dtv, p, pkt + IPV6_HEADER_LEN, IPV6_GET_PLEN(p), pq); return TM_ECODE_OK; case IPPROTO_UDP: IPV6_SET_L4PROTO (p, IPPROTO_UDP); DecodeUDP(tv, dtv, p, pkt + IPV6_HEADER_LEN, IPV6_GET_PLEN(p), pq); return TM_ECODE_OK; case IPPROTO_ICMPV6: IPV6_SET_L4PROTO (p, IPPROTO_ICMPV6); DecodeICMPV6(tv, dtv, p, pkt + IPV6_HEADER_LEN, IPV6_GET_PLEN(p), pq); return TM_ECODE_OK; case IPPROTO_SCTP: IPV6_SET_L4PROTO (p, IPPROTO_SCTP); DecodeSCTP(tv, dtv, p, pkt + IPV6_HEADER_LEN, IPV6_GET_PLEN(p), pq); return TM_ECODE_OK; case IPPROTO_IPIP: IPV6_SET_L4PROTO(p, IPPROTO_IPIP); DecodeIPv4inIPv6(tv, dtv, p, pkt + IPV6_HEADER_LEN, IPV6_GET_PLEN(p), pq); return TM_ECODE_OK; case IPPROTO_IPV6: DecodeIP6inIP6(tv, dtv, p, pkt + IPV6_HEADER_LEN, IPV6_GET_PLEN(p), pq); return TM_ECODE_OK; case IPPROTO_FRAGMENT: case IPPROTO_HOPOPTS: case IPPROTO_ROUTING: case IPPROTO_NONE: case IPPROTO_DSTOPTS: case IPPROTO_AH: case IPPROTO_ESP: case IPPROTO_MH: case IPPROTO_HIP: case IPPROTO_SHIM6: DecodeIPV6ExtHdrs(tv, dtv, p, pkt + IPV6_HEADER_LEN, IPV6_GET_PLEN(p), pq); break; case IPPROTO_ICMP: ENGINE_SET_EVENT(p,IPV6_WITH_ICMPV4); break; default: ENGINE_SET_EVENT(p, IPV6_UNKNOWN_NEXT_HEADER); IPV6_SET_L4PROTO (p, IPV6_GET_NH(p)); break; } p->proto = IPV6_GET_L4PROTO (p); /* Pass to defragger if a fragment. */ if (IPV6_EXTHDR_ISSET_FH(p)) { Packet *rp = Defrag(tv, dtv, p, pq); if (rp != NULL) { PacketEnqueue(pq,rp); } } return TM_ECODE_OK; }