Project

General

Profile

Bug #315 » 0001-Fix-PF_RING-off-by-one-error-when-dealing-with-a-ful.patch

Will Metcalf, 08/11/2011 01:53 PM

View differences:

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);
}
}
(1-1/2)