/** * \brief Write a pid file (used at the startup) * This commonly needed by the init scripts * * \param pointer to the name of the pid file to write (optarg) * * \retval 0 if succes * \retval -1 on failure */ int SCPidfileCreate(const char *pidfile) { SCEnter(); int pidfd = 0; char val[16]; size_t len = snprintf(val, sizeof(val), "%"PRIuMAX"\n", (uintmax_t)getpid()); if (len <= 0) { SCLogError(SC_ERR_PIDFILE_SNPRINTF, "Pid error (%s)", strerror(errno)); SCReturnInt(-1); } pidfd = open(pidfile, O_CREAT | O_TRUNC | O_NOFOLLOW | O_WRONLY, 0644); if (pidfd < 0) { SCLogError(SC_ERR_PIDFILE_OPEN, "unable to set pidfile '%s': %s", pidfile, strerror(errno)); SCReturnInt(-1); } ssize_t r = write(pidfd, val, (unsigned int)len); if (r == -1) { SCLogError(SC_ERR_PIDFILE_WRITE, "unable to write pidfile: %s", strerror(errno)); close(pidfd); SCReturnInt(-1); } else if ((size_t)r != len) { SCLogError(SC_ERR_PIDFILE_WRITE, "unable to write pidfile: wrote" " %"PRIdMAX" of %"PRIuMAX" bytes.", (intmax_t)r, (uintmax_t)len); close(pidfd); SCReturnInt(-1); } close(pidfd); SCReturnInt(0); }
/** * \internal * \brief This function is used to match flags on a packet with those passed via dsize: * * \param t pointer to thread vars * \param det_ctx pointer to the pattern matcher thread * \param p pointer to the current packet * \param s pointer to the Signature * \param m pointer to the sigmatch * * \retval 0 no match * \retval 1 match */ int DetectDsizeMatch (ThreadVars *t, DetectEngineThreadCtx *det_ctx, Packet *p, Signature *s, SigMatch *m) { SCEnter(); int ret = 0; if (PKT_IS_PSEUDOPKT(p)) { SCReturnInt(0); } DetectDsizeData *dd = (DetectDsizeData *)m->ctx; SCLogDebug("p->payload_len %"PRIu16"", p->payload_len); if (dd->mode == DETECTDSIZE_EQ && dd->dsize == p->payload_len) ret = 1; else if (dd->mode == DETECTDSIZE_LT && p->payload_len < dd->dsize) ret = 1; else if (dd->mode == DETECTDSIZE_GT && p->payload_len > dd->dsize) ret = 1; else if (dd->mode == DETECTDSIZE_RA && p->payload_len > dd->dsize && p->payload_len < dd->dsize2) ret = 1; SCReturnInt(ret); }
TmEcode LogFilestoreLog (ThreadVars *tv, Packet *p, void *data, PacketQueue *pq, PacketQueue *postpq) { SCEnter(); int r = TM_ECODE_OK; /* no flow, no htp state */ if (p->flow == NULL) { SCReturnInt(TM_ECODE_OK); } if (!(PKT_IS_TCP(p))) { SCReturnInt(TM_ECODE_OK); } SCLogDebug("p->pcap_cnt %"PRIu64, p->pcap_cnt); if (PKT_IS_IPV4(p)) { r = LogFilestoreLogIPv4(tv, p, data, pq, postpq); } else if (PKT_IS_IPV6(p)) { r = LogFilestoreLogIPv6(tv, p, data, pq, postpq); } SCReturnInt(r); }
/** * \brief Check if a SigGroupHead contains a Signature, whose sid is sent as an * argument. * * \param de_ctx Pointer to the detection engine context. * \param sgh Pointer to the SigGroupHead that has to be checked for the * presence of a Signature. * \param sid The Signature id(sid) that has to be checked in the SigGroupHead. * * \retval 1 On successfully finding the sid in the SigGroupHead. * \retval 0 If the sid is not found in the SigGroupHead */ int SigGroupHeadContainsSigId(DetectEngineCtx *de_ctx, SigGroupHead *sgh, uint32_t sid) { SCEnter(); uint32_t sig = 0; Signature *s = NULL; uint32_t max_sid = DetectEngineGetMaxSigId(de_ctx); if (sgh == NULL) { SCReturnInt(0); } for (sig = 0; sig < max_sid; sig++) { if (sgh->init->sig_array == NULL) { SCReturnInt(0); } /* Check if the SigGroupHead has an entry for the sid */ if ( !(sgh->init->sig_array[sig / 8] & (1 << (sig % 8))) ) continue; /* If we have reached here, we have an entry for sid in the SigGrouHead. * Retrieve the Signature from the detection engine context */ s = de_ctx->sig_array[sig]; if (s == NULL) continue; /* If the retrieved Signature matches the sid arg, we have a match */ if (s->id == sid) { SCReturnInt(1); } } SCReturnInt(0); }
/** * \brief this function is used to parse urilen data into the current signature * * \param de_ctx pointer to the Detection Engine Context * \param s pointer to the Current Signature * \param urilenstr pointer to the user provided urilen options * * \retval 0 on Success * \retval -1 on Failure */ static int DetectUrilenSetup (DetectEngineCtx *de_ctx, Signature *s, char *urilenstr) { SCEnter(); DetectUrilenData *urilend = NULL; SigMatch *sm = NULL; if (s->alproto != ALPROTO_UNKNOWN && s->alproto != ALPROTO_HTTP) { SCLogError(SC_ERR_CONFLICTING_RULE_KEYWORDS, "rule contains a non http " "alproto set"); goto error; } urilend = DetectUrilenParse(urilenstr); if (urilend == NULL) goto error; sm = SigMatchAlloc(); if (sm == NULL) goto error; sm->type = DETECT_AL_URILEN; sm->ctx = (void *)urilend; if (urilend->raw_buffer) SigMatchAppendSMToList(s, sm, DETECT_SM_LIST_HRUDMATCH); else SigMatchAppendSMToList(s, sm, DETECT_SM_LIST_UMATCH); /* Flagged the signature as to inspect the app layer data */ s->flags |= SIG_FLAG_APPLAYER; s->alproto = ALPROTO_HTTP; SCReturnInt(0); error: DetectUrilenFree(urilend); SCReturnInt(-1); }
/** \brief Function to return the default bloomfilter size for the mpm algorithm, * which has been defined by the user in the config file * * \param conf_val pointer to the string value of bloom filter size * \retval bloom_value returns the bloom filter value as defined by user, * otherwise default medium size value */ uint32_t MpmGetBloomSize(const char *conf_val) { SCEnter(); uint32_t bloom_value = BLOOMSIZE_MEDIUM; if(strncmp(conf_val, "low", 3) == 0) { bloom_value = BLOOMSIZE_LOW; } else if(strncmp(conf_val, "medium", 6) == 0) { bloom_value = BLOOMSIZE_MEDIUM; } else if(strncmp(conf_val, "high", 4) == 0) { bloom_value = BLOOMSIZE_HIGH; } SCReturnInt(bloom_value); }
/** * \brief This function passes off to link type decoders. * * DecodePcap reads packets from the PacketQueue and passes * them off to the proper link type decoder. * * \param t pointer to ThreadVars * \param p pointer to the current packet * \param data pointer that gets cast into PcapThreadVars for ptv * \param pq pointer to the current PacketQueue */ TmEcode DecodePcap(ThreadVars *tv, Packet *p, void *data, PacketQueue *pq, PacketQueue *postpq) { SCEnter(); DecodeThreadVars *dtv = (DecodeThreadVars *)data; /* XXX HACK: flow timeout can call us for injected pseudo packets * see bug: https://redmine.openinfosecfoundation.org/issues/1107 */ if (p->flags & PKT_PSEUDO_STREAM_END) return TM_ECODE_OK; /* update counters */ SCPerfCounterIncr(dtv->counter_pkts, tv->sc_perf_pca); // SCPerfCounterIncr(dtv->counter_pkts_per_sec, tv->sc_perf_pca); SCPerfCounterAddUI64(dtv->counter_bytes, tv->sc_perf_pca, GET_PKT_LEN(p)); #if 0 SCPerfCounterAddDouble(dtv->counter_bytes_per_sec, tv->sc_perf_pca, GET_PKT_LEN(p)); SCPerfCounterAddDouble(dtv->counter_mbit_per_sec, tv->sc_perf_pca, (GET_PKT_LEN(p) * 8)/1000000.0); #endif SCPerfCounterAddUI64(dtv->counter_avg_pkt_size, tv->sc_perf_pca, GET_PKT_LEN(p)); SCPerfCounterSetUI64(dtv->counter_max_pkt_size, tv->sc_perf_pca, GET_PKT_LEN(p)); /* call the decoder */ switch(p->datalink) { case LINKTYPE_LINUX_SLL: DecodeSll(tv, dtv, p, GET_PKT_DATA(p), GET_PKT_LEN(p), pq); break; case LINKTYPE_ETHERNET: DecodeEthernet(tv, dtv, p,GET_PKT_DATA(p), GET_PKT_LEN(p), pq); break; case LINKTYPE_PPP: DecodePPP(tv, dtv, p, GET_PKT_DATA(p), GET_PKT_LEN(p), pq); break; case LINKTYPE_RAW: DecodeRaw(tv, dtv, p, GET_PKT_DATA(p), GET_PKT_LEN(p), pq); break; default: SCLogError(SC_ERR_DATALINK_UNIMPLEMENTED, "Error: datalink type %" PRId32 " not yet supported in module DecodePcap", p->datalink); break; } PacketDecodeFinalize(tv, dtv, p); SCReturnInt(TM_ECODE_OK); }
/** * \internal * \brief Apply the prefilter keyword to the last match * \param det_ctx detection engine ctx * \param s signature * \param nullstr should be null * \retval 0 ok * \retval -1 failure */ static int DetectPrefilterSetup (DetectEngineCtx *de_ctx, Signature *s, char *nullstr) { SCEnter(); SigMatch *sm = NULL; int ret = -1; if (nullstr != NULL) { SCLogError(SC_ERR_INVALID_VALUE, "prefilter has value"); goto end; } if (s->flags & SIG_FLAG_PREFILTER) { SCLogError(SC_ERR_INVALID_SIGNATURE, "prefilter already set"); goto end; } sm = SigMatchGetLastSM(s); if (sm == NULL) { SCLogError(SC_ERR_INVALID_SIGNATURE, "prefilter needs preceding match"); goto end; } s->prefilter_sm = sm; s->flags |= SIG_FLAG_PREFILTER; /* if the sig match is content, prefilter should act like * 'fast_pattern' w/o options. */ if (sm->type == DETECT_CONTENT) { DetectContentData *cd = (DetectContentData *)sm->ctx; if ((cd->flags & DETECT_CONTENT_NEGATED) && ((cd->flags & DETECT_CONTENT_DISTANCE) || (cd->flags & DETECT_CONTENT_WITHIN) || (cd->flags & DETECT_CONTENT_OFFSET) || (cd->flags & DETECT_CONTENT_DEPTH))) { SCLogError(SC_ERR_INVALID_SIGNATURE, "prefilter; cannot be " "used with negated content, along with relative modifiers"); goto end; } cd->flags |= DETECT_CONTENT_FAST_PATTERN; } ret = 0; end: SCReturnInt(ret); }
/** * \brief This function is used to match flow flags set on a packet with those passed via flow: * * \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 DetectFlowData * * \retval 0 no match * \retval 1 match */ int DetectFlowMatch (ThreadVars *t, DetectEngineThreadCtx *det_ctx, Packet *p, Signature *s, SigMatch *m) { SCEnter(); SCLogDebug("pkt %p", p); if (p->flowflags & FLOW_PKT_TOSERVER) { SCLogDebug("FLOW_PKT_TOSERVER"); } else if (p->flowflags & FLOW_PKT_TOCLIENT) { SCLogDebug("FLOW_PKT_TOCLIENT"); } if (p->flowflags & FLOW_PKT_ESTABLISHED) { SCLogDebug("FLOW_PKT_ESTABLISHED"); } else if (p->flowflags & FLOW_PKT_STATELESS) { SCLogDebug("FLOW_PKT_STATELESS"); } uint8_t cnt = 0; DetectFlowData *fd = (DetectFlowData *)m->ctx; if (fd->flags & FLOW_PKT_TOSERVER && p->flowflags & FLOW_PKT_TOSERVER) { cnt++; } else if (fd->flags & FLOW_PKT_TOCLIENT && p->flowflags & FLOW_PKT_TOCLIENT) { cnt++; } if (fd->flags & FLOW_PKT_ESTABLISHED && p->flowflags & FLOW_PKT_ESTABLISHED) { cnt++; } else if (fd->flags & FLOW_PKT_STATELESS) { cnt++; } if (det_ctx->flags & DETECT_ENGINE_THREAD_CTX_STREAM_CONTENT_MATCH) { if (fd->flags & FLOW_PKT_ONLYSTREAM) cnt++; } else { if (fd->flags & FLOW_PKT_NOSTREAM) cnt++; } int ret = (fd->match_cnt == cnt) ? 1 : 0; SCLogDebug("returning %" PRId32 " cnt %" PRIu8 " fd->match_cnt %" PRId32 " fd->flags 0x%02X p->flowflags 0x%02X", ret, cnt, fd->match_cnt, fd->flags, p->flowflags); SCReturnInt(ret); }
static int StreamTcpSackTest12 (void) { TcpStream stream; int retval = 0; memset(&stream, 0, sizeof(stream)); stream.window = 2000; StreamTcpSackInsertRange(&stream, 800, 1000); StreamTcpSackInsertRange(&stream, 700, 900); StreamTcpSackInsertRange(&stream, 600, 800); StreamTcpSackInsertRange(&stream, 500, 700); StreamTcpSackInsertRange(&stream, 100, 600); #ifdef DEBUG StreamTcpSackPrintList(&stream); #endif /* DEBUG */ if (stream.sack_head->le != 100) { goto end; } if (StreamTcpSackedSize(&stream) != 900) { printf("size should be 900, is %u: ", StreamTcpSackedSize(&stream)); goto end; } StreamTcpSackInsertRange(&stream, 0, 1000); if (StreamTcpSackedSize(&stream) != 1000) { printf("size should be 1000, is %u: ", StreamTcpSackedSize(&stream)); goto end; } stream.last_ack = 500; StreamTcpSackPruneList(&stream); if (StreamTcpSackedSize(&stream) != 500) { printf("size should be 500, is %u: ", StreamTcpSackedSize(&stream)); goto end; } retval = 1; end: SCReturnInt(retval); }
/** * \brief Main NFQ reading Loop function */ TmEcode ReceiveNFQLoop(ThreadVars *tv, void *data, void *slot) { SCEnter(); NFQThreadVars *ntv = (NFQThreadVars *)data; NFQQueueVars *nq = NFQGetQueue(ntv->nfq_index); ntv->slot = ((TmSlot *) slot)->slot_next; while(1) { if (suricata_ctl_flags != 0) { break; } NFQRecvPkt(nq, ntv); SCPerfSyncCountersIfSignalled(tv, 0); } SCReturnInt(TM_ECODE_OK); }
TmEcode DecodePcapFile(ThreadVars *tv, Packet *p, void *data, PacketQueue *pq, PacketQueue *postpq) { SCEnter(); DecodeThreadVars *dtv = (DecodeThreadVars *)data; /* XXX HACK: flow timeout can call us for injected pseudo packets * see bug: https://redmine.openinfosecfoundation.org/issues/1107 */ if (p->flags & PKT_PSEUDO_STREAM_END) return TM_ECODE_OK; /* update counters */ SCPerfCounterIncr(dtv->counter_pkts, tv->sc_perf_pca); // SCPerfCounterIncr(dtv->counter_pkts_per_sec, tv->sc_perf_pca); SCPerfCounterAddUI64(dtv->counter_bytes, tv->sc_perf_pca, GET_PKT_LEN(p)); #if 0 SCPerfCounterAddDouble(dtv->counter_bytes_per_sec, tv->sc_perf_pca, GET_PKT_LEN(p)); SCPerfCounterAddDouble(dtv->counter_mbit_per_sec, tv->sc_perf_pca, (GET_PKT_LEN(p) * 8)/1000000.0 ); #endif SCPerfCounterAddUI64(dtv->counter_avg_pkt_size, tv->sc_perf_pca, GET_PKT_LEN(p)); SCPerfCounterSetUI64(dtv->counter_max_pkt_size, tv->sc_perf_pca, GET_PKT_LEN(p)); double curr_ts = p->ts.tv_sec + p->ts.tv_usec / 1000.0; if (curr_ts < prev_signaled_ts || (curr_ts - prev_signaled_ts) > 60.0) { prev_signaled_ts = curr_ts; FlowWakeupFlowManagerThread(); } /* update the engine time representation based on the timestamp * of the packet. */ TimeSet(&p->ts); /* call the decoder */ pcap_g.Decoder(tv, dtv, p, GET_PKT_DATA(p), GET_PKT_LEN(p), pq); #ifdef DEBUG BUG_ON(p->pkt_src != PKT_SRC_WIRE && p->pkt_src != PKT_SRC_FFR_V2); #endif PacketDecodeFinalize(tv, dtv, p); SCReturnInt(TM_ECODE_OK); }
static int LogTcpDataLoggerDir(ThreadVars *tv, void *thread_data, const Flow *f, const uint8_t *data, uint32_t data_len, uint64_t tx_id, uint8_t flags) { SCEnter(); LogTcpDataLogThread *aft = thread_data; LogTcpDataFileCtx *td = aft->tcpdatalog_ctx; const char *mode = "a"; if (flags & OUTPUT_STREAMING_FLAG_OPEN) mode = "w"; if (data && data_len) { char srcip[46] = "", dstip[46] = ""; if (FLOW_IS_IPV4(f)) { PrintInet(AF_INET, (const void *)&f->src.addr_data32[0], srcip, sizeof(srcip)); PrintInet(AF_INET, (const void *)&f->dst.addr_data32[0], dstip, sizeof(dstip)); } else if (FLOW_IS_IPV6(f)) { PrintInet(AF_INET6, (const void *)f->src.addr_data32, srcip, sizeof(srcip)); PrintInet(AF_INET6, (const void *)f->dst.addr_data32, dstip, sizeof(dstip)); } char name[PATH_MAX]; char tx[64] = { 0 }; if (flags & OUTPUT_STREAMING_FLAG_TRANSACTION) { snprintf(tx, sizeof(tx), "%"PRIu64, tx_id); } snprintf(name, sizeof(name), "%s/%s/%s_%u-%s_%u-%s-%s.data", td->log_dir, td->type == STREAMING_HTTP_BODIES ? "http" : "tcp", srcip, f->sp, dstip, f->dp, tx, flags & OUTPUT_STREAMING_FLAG_TOSERVER ? "ts" : "tc"); FILE *fp = fopen(name, mode); BUG_ON(fp == NULL); // PrintRawDataFp(stdout, (uint8_t *)data, data_len); fwrite(data, data_len, 1, fp); fclose(fp); } SCReturnInt(TM_ECODE_OK); }
int RunModeIdsAFPAutoFp(DetectEngineCtx *de_ctx) { SCEnter(); /* We include only if AF_PACKET is enabled */ #ifdef HAVE_AF_PACKET int ret; char *live_dev = NULL; RunModeInitialize(); TimeModeSetLive(); (void)ConfGet("af-packet.live-interface", &live_dev); SCLogDebug("live_dev %s", live_dev); if (AFPPeersListInit() != TM_ECODE_OK) { SCLogError(SC_ERR_RUNMODE, "Unable to init peers list."); exit(EXIT_FAILURE); } ret = RunModeSetLiveCaptureAutoFp(de_ctx, ParseAFPConfig, AFPConfigGeThreadsCount, "ReceiveAFP", "DecodeAFP", "RxAFP", live_dev); if (ret != 0) { SCLogError(SC_ERR_RUNMODE, "Unable to start runmode"); exit(EXIT_FAILURE); } /* In IPS mode each threads must have a peer */ if (AFPPeersListCheck() != TM_ECODE_OK) { SCLogError(SC_ERR_RUNMODE, "Some IPS capture threads did not peer."); exit(EXIT_FAILURE); } SCLogInfo("RunModeIdsAFPAutoFp initialised"); #endif /* HAVE_AF_PACKET */ SCReturnInt(0); }
static int DetectAppLayerEventAppMatch(ThreadVars *t, DetectEngineThreadCtx *det_ctx, Flow *f, uint8_t flags, void *state, Signature *s, SigMatch *m) { SCEnter(); AppLayerDecoderEvents *decoder_events = NULL; int r = 0; DetectAppLayerEventData *aled = (DetectAppLayerEventData *)m->ctx; if (r == 0) { decoder_events = AppLayerParserGetDecoderEvents(f->alparser); if (decoder_events != NULL && AppLayerDecoderEventsIsEventSet(decoder_events, aled->event_id)) { r = 1; } } SCReturnInt(r); }
/** * \brief Add IPv4 header data, to be stored in the Additional Data * field of the IDMEF alert (see section 4.2.4.6 of RFC 4765). * * \return 0 if ok */ static int PacketToDataV4(Packet *p, PacketAlert *pa, idmef_alert_t *alert) { SCEnter(); AddIntData(alert, "ip_ver", IPV4_GET_RAW_VER(p->ip4h)); AddIntData(alert, "ip_hlen", IPV4_GET_RAW_HLEN(p->ip4h)); AddIntData(alert, "ip_tos", IPV4_GET_RAW_IPTOS(p->ip4h)); AddIntData(alert, "ip_len", ntohs(IPV4_GET_RAW_IPLEN(p->ip4h))); AddIntData(alert, "ip_id", ntohs(IPV4_GET_RAW_IPID(p->ip4h))); AddIntData(alert, "ip_off", ntohs(IPV4_GET_RAW_IPOFFSET(p->ip4h))); AddIntData(alert, "ip_ttl", IPV4_GET_RAW_IPTTL(p->ip4h)); AddIntData(alert, "ip_proto", IPV4_GET_RAW_IPPROTO(p->ip4h)); AddIntData(alert, "ip_sum", ntohs(p->ip4h->ip_csum)); SCReturnInt(0); }
int DetectAppLayerEventMatch(ThreadVars *t, DetectEngineThreadCtx *det_ctx, Flow *f, uint8_t flags, void *state, Signature *s, SigMatch *m) { SCEnter(); int r = 0; DetectAppLayerEventData *aled = (DetectAppLayerEventData *)m->ctx; FLOWLOCK_RDLOCK(f); AppLayerDecoderEvents *decoder_events = AppLayerGetDecoderEventsForFlow(f); if (decoder_events != NULL && AppLayerDecoderEventsIsEventSet(decoder_events, aled->event_id)) { r = 1; } FLOWLOCK_UNLOCK(f); SCReturnInt(r); }
/** * \brief Create the hash for threshold tables * * \param ht Hash Table * \param data Data that will be used to create the hash * \param datalen Data length * * \retval hash the hash */ uint32_t ThresholdHashFunc(HashListTable *ht, void *data, uint16_t datalen) { SCEnter(); DetectThresholdEntry *dt = (DetectThresholdEntry *)data; uint32_t hash = 0; if (dt->ipv == 4) hash = (dt->sid + dt->gid + dt->addr.addr_data32[0]); else if (dt->ipv == 6) hash = (dt->sid + dt->gid + dt->addr.addr_data32[0] + dt->addr.addr_data32[1] + dt->addr.addr_data32[2] + dt->addr.addr_data32[3]); else { SCLogDebug("no dt->ipv"); } SCReturnInt(hash % THRESHOLD_HASH_SIZE); }
/** \brief Verify and store a match * * used at search runtime * * \param thread_ctx mpm thread ctx * \param pmq storage for match results * \param list end match to check against (entire list will be checked) * \param offset match offset in the buffer * \param patlen length of the pattern we're checking * * \retval 0 no match after all * \retval 1 (new) match */ int MpmVerifyMatch(MpmThreadCtx *thread_ctx, PatternMatcherQueue *pmq, uint32_t patid) { SCEnter(); /* Handle pattern id storage */ if (pmq != NULL && pmq->pattern_id_bitarray != NULL) { SCLogDebug("using pattern id arrays, storing %"PRIu32, patid); if (!(pmq->pattern_id_bitarray[(patid / 8)] & (1<<(patid % 8)))) { /* flag this pattern id as being added now */ pmq->pattern_id_bitarray[(patid / 8)] |= (1<<(patid % 8)); /* append the pattern_id to the array with matches */ pmq->pattern_id_array[pmq->pattern_id_array_cnt] = patid; pmq->pattern_id_array_cnt++; SCLogDebug("pattern_id_array_cnt %u", pmq->pattern_id_array_cnt); } } SCReturnInt(1); }
static int StreamTcpSackTest09 (void) { TcpStream stream; int retval = 0; memset(&stream, 0, sizeof(stream)); stream.window = 100; StreamTcpSackInsertRange(&stream, 0, 9); StreamTcpSackInsertRange(&stream, 11, 19); StreamTcpSackInsertRange(&stream, 21, 29); StreamTcpSackInsertRange(&stream, 31, 39); StreamTcpSackInsertRange(&stream, 0, 40); #ifdef DEBUG StreamTcpSackPrintList(&stream); #endif /* DEBUG */ if (stream.sack_head->le != 0) { goto end; } if (StreamTcpSackedSize(&stream) != 40) { printf("size should be 40, is %u: ", StreamTcpSackedSize(&stream)); goto end; } stream.last_ack = 39; StreamTcpSackPruneList(&stream); if (StreamTcpSackedSize(&stream) != 1) { printf("size should be 1, is %u: ", StreamTcpSackedSize(&stream)); goto end; } retval = 1; end: SCReturnInt(retval); }
/** * \brief This function passes off to link type decoders. * * DecodePcap reads packets from the PacketQueue and passes * them off to the proper link type decoder. * * \param t pointer to ThreadVars * \param p pointer to the current packet * \param data pointer that gets cast into PcapThreadVars for ptv * \param pq pointer to the current PacketQueue */ TmEcode DecodePcap(ThreadVars *tv, Packet *p, void *data, PacketQueue *pq, PacketQueue *postpq) { SCEnter(); DecodeThreadVars *dtv = (DecodeThreadVars *)data; /* XXX HACK: flow timeout can call us for injected pseudo packets * see bug: https://redmine.openinfosecfoundation.org/issues/1107 */ if (p->flags & PKT_PSEUDO_STREAM_END) return TM_ECODE_OK; /* update counters */ DecodeUpdatePacketCounters(tv, dtv, p); /* call the decoder */ switch(p->datalink) { case LINKTYPE_LINUX_SLL: DecodeSll(tv, dtv, p, GET_PKT_DATA(p), GET_PKT_LEN(p), pq); break; case LINKTYPE_ETHERNET: DecodeEthernet(tv, dtv, p,GET_PKT_DATA(p), GET_PKT_LEN(p), pq); break; case LINKTYPE_PPP: DecodePPP(tv, dtv, p, GET_PKT_DATA(p), GET_PKT_LEN(p), pq); break; case LINKTYPE_RAW: DecodeRaw(tv, dtv, p, GET_PKT_DATA(p), GET_PKT_LEN(p), pq); break; case LINKTYPE_NULL: DecodeNull(tv, dtv, p, GET_PKT_DATA(p), GET_PKT_LEN(p), pq); break; default: SCLogError(SC_ERR_DATALINK_UNIMPLEMENTED, "Error: datalink type %" PRId32 " not yet supported in module DecodePcap", p->datalink); break; } PacketDecodeFinalize(tv, dtv, p); SCReturnInt(TM_ECODE_OK); }
static int JsonFlowLogger(ThreadVars *tv, void *thread_data, Flow *f) { SCEnter(); JsonFlowLogThread *jhl = (JsonFlowLogThread *)thread_data; /* reset */ MemBufferReset(jhl->buffer); json_t *js = CreateJSONHeaderFromFlow(f, "flow"); if (unlikely(js == NULL)) return TM_ECODE_OK; JsonFlowLogJSON(jhl, js, f); OutputJSONBuffer(js, jhl->flowlog_ctx->file_ctx, &jhl->buffer); json_object_del(js, "http"); json_object_clear(js); json_decref(js); SCReturnInt(TM_ECODE_OK); }
/** * \brief Inspect the file inspecting keywords against the SMTP transactions. * * \param tv thread vars * \param det_ctx detection engine thread ctx * \param f flow * \param s signature to inspect * \param alstate state * \param flags direction flag * * \retval 0 no match * \retval 1 match * \retval 2 can't match * \retval 3 can't match filestore signature * * \note flow is not locked at this time */ int DetectFileInspectSmtp(ThreadVars *tv, DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx, Signature *s, Flow *f, uint8_t flags, void *alstate, void *tx, uint64_t tx_id) { SCEnter(); int r = DETECT_ENGINE_INSPECT_SIG_NO_MATCH; SMTPState *smtp_state = NULL; FileContainer *ffc; smtp_state = (SMTPState *)alstate; if (smtp_state == NULL) { SCLogDebug("no SMTP state"); goto end; } if (flags & STREAM_TOSERVER) ffc = smtp_state->files_ts; else goto end; int match = DetectFileInspect(tv, det_ctx, f, s, flags, ffc); if (match == DETECT_ENGINE_INSPECT_SIG_MATCH) { r = DETECT_ENGINE_INSPECT_SIG_MATCH; } else if (match == DETECT_ENGINE_INSPECT_SIG_CANT_MATCH) { SCLogDebug("sid %u can't match on this transaction", s->id); r = DETECT_ENGINE_INSPECT_SIG_CANT_MATCH; } else if (match == DETECT_ENGINE_INSPECT_SIG_CANT_MATCH_FILESTORE) { SCLogDebug("sid %u can't match on this transaction (filestore sig)", s->id); r = DETECT_ENGINE_INSPECT_SIG_CANT_MATCH_FILESTORE; } else if (match == DETECT_ENGINE_INSPECT_SIG_MATCH_MORE_FILES) { SCLogDebug("match with more files ahead"); r = match; } end: SCReturnInt(r); }
/** * \brief This function is used to match flow flags set on a packet with those passed via flow: * * \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 DetectFlowData * * \retval 0 no match * \retval 1 match */ int DetectFlowMatch (ThreadVars *t, DetectEngineThreadCtx *det_ctx, Packet *p, Signature *s, const SigMatchCtx *ctx) { SCEnter(); SCLogDebug("pkt %p", p); if (p->flowflags & FLOW_PKT_TOSERVER) { SCLogDebug("FLOW_PKT_TOSERVER"); } else if (p->flowflags & FLOW_PKT_TOCLIENT) { SCLogDebug("FLOW_PKT_TOCLIENT"); } if (p->flowflags & FLOW_PKT_ESTABLISHED) { SCLogDebug("FLOW_PKT_ESTABLISHED"); } const DetectFlowData *fd = (const DetectFlowData *)ctx; int ret = FlowMatch(p->flags, p->flowflags, det_ctx->flags, fd->flags, fd->match_cnt);; SCLogDebug("returning %" PRId32 " fd->match_cnt %" PRId32 " fd->flags 0x%02X p->flowflags 0x%02X", ret, fd->match_cnt, fd->flags, p->flowflags); SCReturnInt(ret); }
/** * \brief This function is used to match filesize rule option. * * \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 DetectFilesizeData * * \retval 0 no match * \retval 1 match */ static int DetectFilesizeMatch (ThreadVars *t, DetectEngineThreadCtx *det_ctx, Flow *f, uint8_t flags, File *file, Signature *s, SigMatch *m) { SCEnter(); DetectFilesizeData *fsd = (DetectFilesizeData *)m->ctx; int ret = 0; uint64_t file_size = FileSize(file); SCLogDebug("file size %"PRIu64", check %"PRIu64, file_size, fsd->size1); if (file->state == FILE_STATE_CLOSED) { switch (fsd->mode) { case DETECT_FILESIZE_EQ: if (file_size == fsd->size1) ret = 1; break; case DETECT_FILESIZE_LT: if (file_size < fsd->size1) ret = 1; break; case DETECT_FILESIZE_GT: if (file_size > fsd->size1) ret = 1; break; case DETECT_FILESIZE_RA: if (file_size > fsd->size1 && file_size < fsd->size2) ret = 1; break; } /* truncated, error: only see if what we have meets the GT condition */ } else if (file->state > FILE_STATE_CLOSED) { if (fsd->mode == DETECT_FILESIZE_GT && file_size > fsd->size1) ret = 1; } SCReturnInt(ret); }
/** * \brief This function passes off to link type decoders. * * DecodeErfDag reads packets from the PacketQueue and passes * them off to the proper link type decoder. * * \param t pointer to ThreadVars * \param p pointer to the current packet * \param data pointer that gets cast into PcapThreadVars for ptv * \param pq pointer to the current PacketQueue */ TmEcode DecodeErfDag(ThreadVars *tv, Packet *p, void *data, PacketQueue *pq, PacketQueue *postpq) { SCEnter(); DecodeThreadVars *dtv = (DecodeThreadVars *)data; /* update counters */ SCPerfCounterIncr(dtv->counter_pkts, tv->sc_perf_pca); // SCPerfCounterIncr(dtv->counter_pkts_per_sec, tv->sc_perf_pca); SCPerfCounterAddUI64(dtv->counter_bytes, tv->sc_perf_pca, GET_PKT_LEN(p)); #if 0 SCPerfCounterAddDouble(dtv->counter_bytes_per_sec, tv->sc_perf_pca, GET_PKT_LEN(p)); SCPerfCounterAddDouble(dtv->counter_mbit_per_sec, tv->sc_perf_pca, (GET_PKT_LEN(p) * 8)/1000000.0); #endif SCPerfCounterAddUI64(dtv->counter_avg_pkt_size, tv->sc_perf_pca, GET_PKT_LEN(p)); SCPerfCounterSetUI64(dtv->counter_max_pkt_size, tv->sc_perf_pca, GET_PKT_LEN(p)); /* call the decoder */ switch(p->datalink) { case LINKTYPE_ETHERNET: DecodeEthernet(tv, dtv, p, GET_PKT_DATA(p), GET_PKT_LEN(p), pq); break; default: SCLogError(SC_ERR_DATALINK_UNIMPLEMENTED, "Error: datalink type %" PRId32 " not yet supported in module DecodeErfDag", p->datalink); break; } PacketDecodeFinalize(tv, dtv, p); SCReturnInt(TM_ECODE_OK); }
/** * \brief Decode the ERF file. * * This function ups the decoder counters and then passes the packet * off to the ethernet decoder. */ TmEcode DecodeErfFile(ThreadVars *tv, Packet *p, void *data, PacketQueue *pq, PacketQueue *postpq) { SCEnter(); DecodeThreadVars *dtv = (DecodeThreadVars *)data; /* Update counters. */ SCPerfCounterIncr(dtv->counter_pkts, tv->sc_perf_pca); // SCPerfCounterIncr(dtv->counter_pkts_per_sec, tv->sc_perf_pca); SCPerfCounterAddUI64(dtv->counter_bytes, tv->sc_perf_pca, GET_PKT_LEN(p)); #if 0 SCPerfCounterAddDouble(dtv->counter_bytes_per_sec, tv->sc_perf_pca, GET_PKT_LEN(p)); SCPerfCounterAddDouble(dtv->counter_mbit_per_sec, tv->sc_perf_pca, (GET_PKT_LEN(p) * 8)/1000000.0 ); #endif SCPerfCounterAddUI64(dtv->counter_avg_pkt_size, tv->sc_perf_pca, GET_PKT_LEN(p)); SCPerfCounterSetUI64(dtv->counter_max_pkt_size, tv->sc_perf_pca, GET_PKT_LEN(p)); DecodeEthernet(tv, dtv, p, GET_PKT_DATA(p), GET_PKT_LEN(p), pq); SCReturnInt(TM_ECODE_OK); }
static int LogTcpDataLoggerFile(ThreadVars *tv, void *thread_data, const Flow *f, const uint8_t *data, uint32_t data_len, uint64_t tx_id, uint8_t flags) { SCEnter(); LogTcpDataLogThread *aft = thread_data; LogTcpDataFileCtx *td = aft->tcpdatalog_ctx; if (data && data_len) { MemBufferReset(aft->buffer); char srcip[46] = "", dstip[46] = ""; if (FLOW_IS_IPV4(f)) { PrintInet(AF_INET, (const void *)&f->src.addr_data32[0], srcip, sizeof(srcip)); PrintInet(AF_INET, (const void *)&f->dst.addr_data32[0], dstip, sizeof(dstip)); } else if (FLOW_IS_IPV6(f)) { PrintInet(AF_INET6, (const void *)f->src.addr_data32, srcip, sizeof(srcip)); PrintInet(AF_INET6, (const void *)f->dst.addr_data32, dstip, sizeof(dstip)); } char name[PATH_MAX]; snprintf(name, sizeof(name), "%s_%u-%s_%u-%s:", srcip, f->sp, dstip, f->dp, flags & OUTPUT_STREAMING_FLAG_TOSERVER ? "ts" : "tc"); PrintRawUriBuf((char *)aft->buffer->buffer, &aft->buffer->offset, aft->buffer->size, (uint8_t *)name,strlen(name)); MemBufferWriteString(aft->buffer, "\n"); PrintRawDataToBuffer(aft->buffer->buffer, &aft->buffer->offset, aft->buffer->size, (uint8_t *)data,data_len); td->file_ctx->Write((const char *)MEMBUFFER_BUFFER(aft->buffer), MEMBUFFER_OFFSET(aft->buffer), td->file_ctx); } SCReturnInt(TM_ECODE_OK); }
/** * \brief Main NFQ reading Loop function */ TmEcode ReceiveNFQLoop(ThreadVars *tv, void *data, void *slot) { SCEnter(); NFQThreadVars *ntv = (NFQThreadVars *)data; NFQQueueVars *nq = NFQGetQueue(ntv->nfq_index); ntv->slot = ((TmSlot *) slot)->slot_next; while(1) { if (suricata_ctl_flags != 0) { NFQMutexLock(nq); if (nq->qh) { nfq_destroy_queue(nq->qh); nq->qh = NULL; } NFQMutexUnlock(nq); break; } NFQRecvPkt(nq, ntv); StatsSyncCountersIfSignalled(tv); } SCReturnInt(TM_ECODE_OK); }
int AppLayerParserSetup(void) { SCEnter(); AppProto alproto = 0; int flow_proto = 0; memset(&alp_ctx, 0, sizeof(alp_ctx)); /* set the default tx handler if none was set explicitly */ if (AppLayerGetActiveTxIdFuncPtr == NULL) { RegisterAppLayerGetActiveTxIdFunc(AppLayerTransactionGetActiveDetectLog); } /* lets set a default value for stream_depth */ for (flow_proto = 0; flow_proto < FLOW_PROTO_DEFAULT; flow_proto++) { for (alproto = 0; alproto < ALPROTO_MAX; alproto++) { alp_ctx.ctxs[flow_proto][alproto].stream_depth = stream_config.reassembly_depth; } } SCReturnInt(0); }