Bug #315 » 0001-Fix-PF_RING-off-by-one-error-when-dealing-with-a-ful.patch
src/runmode-pfring.c | ||
---|---|---|
static const char *default_mode_auto = NULL;
|
||
static const char *default_mode_autofp = NULL;
|
||
static const char *default_mode_single = NULL;
|
||
const char *RunModeIdsPfringGetDefaultMode(void)
|
||
{
|
||
... | ... | |
"from the same flow can be processed by any "
|
||
"detect thread",
|
||
RunModeIdsPfringAutoFp);
|
||
default_mode_single = "single";
|
||
RunModeRegisterNewRunMode(RUNMODE_PFRING, "single",
|
||
"All processing contained in a single thread, but you can spawn many of them",
|
||
RunModeIdsPfringSingle);
|
||
return;
|
||
}
|
||
... | ... | |
return 0;
|
||
}
|
||
/**
|
||
* \brief Single thread version of the Pcap file processing.
|
||
*/
|
||
int RunModeIdsPfringSingle(DetectEngineCtx *de_ctx)
|
||
{
|
||
SCEnter();
|
||
/* We include only if pfring is enabled */
|
||
#ifdef HAVE_PFRING
|
||
char tname[12];
|
||
uint16_t cpu = 0;
|
||
RunModeInitialize();
|
||
TimeModeSetLive();
|
||
/* Available cpus */
|
||
uint16_t ncpus = UtilCpuGetNumProcessorsOnline();
|
||
/* start with cpu 1 so that if we're creating an odd number of detect
|
||
* threads we're not creating the most on CPU0. */
|
||
if (ncpus > 0)
|
||
cpu = 1;
|
||
int thread;
|
||
int pfring_threads = PfringConfGetThreads();
|
||
if (pfring_threads == 0) {
|
||
pfring_threads = 1;
|
||
}
|
||
/* create the threads */
|
||
for (thread = 0; thread < pfring_threads; thread++) {
|
||
snprintf(tname, sizeof(tname), "Pfring%"PRIu16, thread+1);
|
||
char *thread_name = SCStrdup(tname);
|
||
/* create the threads */
|
||
ThreadVars *tv = TmThreadCreatePacketHandler(thread_name,
|
||
"packetpool", "packetpool",
|
||
"packetpool","packetpool",
|
||
"varslot");
|
||
if (tv == NULL) {
|
||
printf("ERROR: TmThreadsCreate failed\n");
|
||
exit(EXIT_FAILURE);
|
||
}
|
||
TmModule *tm_module = TmModuleGetByName("ReceivePfring");
|
||
if (tm_module == NULL) {
|
||
printf("ERROR: TmModuleGetByName failed for ReceivePcap\n");
|
||
exit(EXIT_FAILURE);
|
||
}
|
||
TmVarSlotSetFuncAppend(tv, tm_module, thread_name);
|
||
tm_module = TmModuleGetByName("DecodePfring");
|
||
if (tm_module == NULL) {
|
||
printf("ERROR: TmModuleGetByName DecodePfring failed\n");
|
||
exit(EXIT_FAILURE);
|
||
}
|
||
TmVarSlotSetFuncAppend(tv, tm_module, NULL);
|
||
tm_module = TmModuleGetByName("StreamTcp");
|
||
if (tm_module == NULL) {
|
||
printf("ERROR: TmModuleGetByName StreamTcp failed\n");
|
||
exit(EXIT_FAILURE);
|
||
}
|
||
TmVarSlotSetFuncAppend(tv, tm_module, NULL);
|
||
tm_module = TmModuleGetByName("Detect");
|
||
if (tm_module == NULL) {
|
||
printf("ERROR: TmModuleGetByName Detect failed\n");
|
||
exit(EXIT_FAILURE);
|
||
}
|
||
TmVarSlotSetFuncAppend(tv, tm_module, (void *)de_ctx);
|
||
SetupOutputs(tv);
|
||
if (threading_set_cpu_affinity) {
|
||
TmThreadSetCPUAffinity(tv, (int)cpu);
|
||
/* If we have more than one core/cpu, the first PF_RING thread
|
||
* (at cpu 0) will have less priority (higher 'nice' value)
|
||
* In this case we will set the thread priority to +10 (default is 0)
|
||
*/
|
||
if (cpu == 0 && ncpus > 1) {
|
||
TmThreadSetThreadPriority(tv, PRIO_LOW);
|
||
} else if (ncpus > 1) {
|
||
TmThreadSetThreadPriority(tv, PRIO_MEDIUM);
|
||
}
|
||
}
|
||
if (TmThreadSpawn(tv) != TM_ECODE_OK) {
|
||
printf("ERROR: TmThreadSpawn failed\n");
|
||
exit(EXIT_FAILURE);
|
||
}
|
||
if ((cpu + 1) == ncpus)
|
||
cpu = 0;
|
||
else
|
||
cpu++;
|
||
}
|
||
#endif /* HAVE_PFRING */
|
||
return 0;
|
||
}
|
src/runmode-pfring.h | ||
---|---|---|
int RunModeIdsPfringAuto(DetectEngineCtx *);
|
||
int RunModeIdsPfringAutoFp(DetectEngineCtx *de_ctx);
|
||
int RunModeIdsPfringSingle(DetectEngineCtx *de_ctx);
|
||
void RunModeIdsPfringRegister(void);
|
||
const char *RunModeIdsPfringGetDefaultMode(void);
|
||
src/source-pfring.c | ||
---|---|---|
SCReturnInt(TM_ECODE_FAILED);
|
||
}
|
||
/* Depending on what compile time options are used for pfring we either return 0 or -1 on error and always 1 for success */
|
||
/*
|
||
* Need to use default_packet_size as buff len, PF_RING does bounds checking here and truncates when src buffer is larger than user supplied buffer.
|
||
* Calling GET_PKT_DIRECT_MAX_SIZE() results in an off-by-one error resulting in the last byte in the payload being overwritten
|
||
* by the NULL terminator on a full frame.
|
||
*/
|
||
#ifdef HAVE_PFRING_RECV_UCHAR
|
||
int r = pfring_recv(ptv->pd, (u_char**)&GET_PKT_DIRECT_DATA(p),
|
||
(u_int)GET_PKT_DIRECT_MAX_SIZE(p),
|
||
(uint32_t)default_packet_size,
|
||
&hdr,
|
||
LIBPFRING_WAIT_FOR_INCOMING);
|
||
#else
|
||
int r = pfring_recv(ptv->pd, (char *)GET_PKT_DIRECT_DATA(p),
|
||
(u_int)GET_PKT_DIRECT_MAX_SIZE(p),
|
||
(uint32_t)default_packet_size,
|
||
&hdr,
|
||
LIBPFRING_WAIT_FOR_INCOMING);
|
||
#endif /* HAVE_PFRING_RECV_UCHAR */
|
||
... | ... | |
SCLogInfo("(%s) Pfring Total:%" PRIu64 " Recv:%" PRIu64 " Drop:%" PRIu64 " (%02.1f%%).", tv->name,
|
||
(uint64_t)pfring_s.recv + (uint64_t)pfring_s.drop, (uint64_t)pfring_s.recv,
|
||
(uint64_t)pfring_s.drop, ((float)pfring_s.drop/(float)(pfring_s.drop + pfring_s.recv))*100);
|
||
(uint64_t)pfring_s.drop, ((float)pfring_s.drop/(float)((uint64_t)pfring_s.drop + (uint64_t)pfring_s.recv))*100);
|
||
}
|
||
}
|
||