Add (experimental) support for using multiple pcap devices to acquire packets from. Just passing multiple -i <dev> options on the commandline will activate this. Windows not yet supported.

remotes/origin/master-1.1.x
Victor Julien 15 years ago
parent 18b4e3380f
commit 878d3d87db

@ -2074,37 +2074,80 @@ int RunModeIdsPfring4(DetectEngineCtx *de_ctx, char *iface) {
int RunModeIdsPcapAuto(DetectEngineCtx *de_ctx, char *iface) {
SCEnter();
/* tname = Detect + cpuid, this is 11bytes length as max */
char tname[12];
char tname[16];
uint16_t cpu = 0;
TmModule *tm_module;
uint16_t thread;
RunModeInitialize();
TimeModeSetLive();
/* Available cpus */
uint16_t ncpus = UtilCpuGetNumProcessorsOnline();
int npcap = PcapLiveGetDeviceCount();
TimeModeSetLive();
/* create the threads */
ThreadVars *tv_receivepcap = TmThreadCreatePacketHandler("ReceivePcap","packetpool","packetpool","pickup-queue","simple","1slot");
if (tv_receivepcap == NULL) {
printf("ERROR: TmThreadsCreate failed\n");
exit(EXIT_FAILURE);
}
TmModule *tm_module = TmModuleGetByName("ReceivePcap");
if (tm_module == NULL) {
printf("ERROR: TmModuleGetByName failed for ReceivePcap\n");
exit(EXIT_FAILURE);
}
Tm1SlotSetFunc(tv_receivepcap,tm_module,(void *)iface);
if (npcap == 1) {
/* create the threads */
ThreadVars *tv_receivepcap = TmThreadCreatePacketHandler("ReceivePcap","packetpool","packetpool","pickup-queue","simple","1slot");
if (tv_receivepcap == NULL) {
printf("ERROR: TmThreadsCreate failed\n");
exit(EXIT_FAILURE);
}
tm_module = TmModuleGetByName("ReceivePcap");
if (tm_module == NULL) {
printf("ERROR: TmModuleGetByName failed for ReceivePcap\n");
exit(EXIT_FAILURE);
}
Tm1SlotSetFunc(tv_receivepcap,tm_module,(void *)iface);
if (threading_set_cpu_affinity) {
TmThreadSetCPUAffinity(tv_receivepcap, 0);
if (ncpus > 1)
TmThreadSetThreadPriority(tv_receivepcap, PRIO_MEDIUM);
}
if (threading_set_cpu_affinity) {
TmThreadSetCPUAffinity(tv_receivepcap, 0);
if (ncpus > 1)
TmThreadSetThreadPriority(tv_receivepcap, PRIO_MEDIUM);
}
if (TmThreadSpawn(tv_receivepcap) != TM_ECODE_OK) {
printf("ERROR: TmThreadSpawn failed\n");
exit(EXIT_FAILURE);
}
} else {
SCLogInfo("Using %d pcap device(s).", npcap);
if (TmThreadSpawn(tv_receivepcap) != TM_ECODE_OK) {
printf("ERROR: TmThreadSpawn failed\n");
exit(EXIT_FAILURE);
for (thread = 0; thread < npcap; thread++) {
char *pcap_dev = PcapLiveGetDevice(thread);
if (pcap_dev == NULL) {
printf("Failed to lookup pcap dev %d\n", thread);
exit(EXIT_FAILURE);
}
SCLogDebug("pcap_dev %s", pcap_dev);
snprintf(tname, sizeof(tname),"RecvPcap-%s", pcap_dev);
char *tnamec = SCStrdup(tname);
char *pcap_devc = SCStrdup(pcap_dev);
/* create the threads */
ThreadVars *tv_receivepcap = TmThreadCreatePacketHandler(tnamec,"packetpool","packetpool","pickup-queue","simple","1slot");
if (tv_receivepcap == NULL) {
printf("ERROR: TmThreadsCreate failed\n");
exit(EXIT_FAILURE);
}
tm_module = TmModuleGetByName("ReceivePcap");
if (tm_module == NULL) {
printf("ERROR: TmModuleGetByName failed for ReceivePcap\n");
exit(EXIT_FAILURE);
}
Tm1SlotSetFunc(tv_receivepcap,tm_module,(void *)pcap_devc);
if (threading_set_cpu_affinity) {
TmThreadSetCPUAffinity(tv_receivepcap, 0);
if (ncpus > 1)
TmThreadSetThreadPriority(tv_receivepcap, PRIO_MEDIUM);
}
if (TmThreadSpawn(tv_receivepcap) != TM_ECODE_OK) {
printf("ERROR: TmThreadSpawn failed\n");
exit(EXIT_FAILURE);
}
}
}
#if defined(__SC_CUDA_SUPPORT__)
@ -2265,7 +2308,6 @@ int RunModeIdsPcapAuto(DetectEngineCtx *de_ctx, char *iface) {
if (thread_max < 1)
thread_max = 1;
int thread;
for (thread = 0; thread < thread_max; thread++) {
snprintf(tname, sizeof(tname),"Detect%"PRIu16, thread+1);
if (tname == NULL)

@ -48,8 +48,19 @@
extern uint8_t suricata_ctl_flags;
extern int max_pending_packets;
/** control how many packet libpcap may read in one go */
static int pcap_max_read_packets = 0;
/** storage for pcap device names */
typedef struct PcapDevice_ {
char *dev; /**< the device (e.g. "eth0") */
TAILQ_ENTRY(PcapDevice_) next;
} PcapDevice;
/** private device list */
static TAILQ_HEAD(, PcapDevice_) pcap_devices =
TAILQ_HEAD_INITIALIZER(pcap_devices);
/** max packets < 65536 */
#define PCAP_FILE_MAX_PKTS 256
@ -521,6 +532,66 @@ TmEcode DecodePcapThreadInit(ThreadVars *tv, void *initdata, void **data)
SCReturnInt(TM_ECODE_OK);
}
/**
* \brief Add a pcap device for monitoring
*
* \param dev string with the device name
*
* \retval 0 on success.
* \retval -1 on failure.
*/
int PcapLiveRegisterDevice(char *dev)
{
PcapDevice *pd = SCMalloc(sizeof(PcapDevice));
if (pd == NULL) {
return -1;
}
pd->dev = SCStrdup(dev);
TAILQ_INSERT_TAIL(&pcap_devices, pd, next);
SCLogDebug("Pcap device \"%s\" registered.", dev);
return 0;
}
/**
* \brief Get the number of registered devices
*
* \retval cnt the number of registered devices
*/
int PcapLiveGetDeviceCount(void) {
int i = 0;
PcapDevice *pd;
TAILQ_FOREACH(pd, &pcap_devices, next) {
i++;
}
return i;
}
/**
* \brief Get a pointer to the device at idx
*
* \param number idx of the device in our list
*
* \retval ptr pointer to the string containing the device
* \retval NULL on error
*/
char *PcapLiveGetDevice(int number) {
int i = 0;
PcapDevice *pd;
TAILQ_FOREACH(pd, &pcap_devices, next) {
if (i == number) {
return pd->dev;
}
i++;
}
return NULL;
}
void PcapTranslateIPToDevice(char *pcap_dev, size_t len)
{
char errbuf[PCAP_ERRBUF_SIZE];

@ -28,6 +28,10 @@ void TmModuleReceivePcapRegister (void);
void TmModuleDecodePcapRegister (void);
void PcapTranslateIPToDevice(char *pcap_dev, size_t len);
int PcapLiveRegisterDevice(char *);
int PcapLiveGetDeviceCount(void);
char *PcapLiveGetDevice(int);
/* XXX replace with user configurable options */
#define LIBPCAP_SNAPLEN 1518
#define LIBPCAP_COPYWAIT 500

@ -638,6 +638,17 @@ int main(int argc, char **argv)
case 'i':
if (run_mode == MODE_UNKNOWN) {
run_mode = MODE_PCAP_DEV;
PcapLiveRegisterDevice(optarg);
} else if (run_mode == MODE_PCAP_DEV) {
#ifdef OS_WIN32
SCLogError(SC_ERR_PCAP_MULTI_DEV_NO_SUPPORT, "pcap multi dev "
"support is not (yet) supported on Windows.");
exit(EXIT_FAILURE);
#else
SCLogWarning(SC_WARN_PCAP_MULTI_DEV_EXPERIMENTAL, "using "
"multiple pcap devices to get packets is experimental.");
PcapLiveRegisterDevice(optarg);
#endif
} else {
SCLogError(SC_ERR_MULTIPLE_RUN_MODE, "more than one run mode "
"has been specified");
@ -645,7 +656,7 @@ int main(int argc, char **argv)
exit(EXIT_FAILURE);
}
memset(pcap_dev, 0, sizeof(pcap_dev));
strncpy(pcap_dev, optarg, ((strlen(optarg) < sizeof(pcap_dev)) ? (strlen(optarg)) : (sizeof(pcap_dev)-1)));
strlcpy(pcap_dev, optarg, ((strlen(optarg) < sizeof(pcap_dev)) ? (strlen(optarg)+1) : (sizeof(pcap_dev))));
break;
case 'l':
if (ConfSet("default-log-dir", optarg, 0) != 1) {

@ -192,6 +192,8 @@ const char * SCErrorToString(SCError err)
CASE_CODE (SC_ERR_DCERPC);
CASE_CODE (SC_ERR_AHO_CORASICK);
CASE_CODE (SC_ERR_REFERENCE_CONFIG);
CASE_CODE (SC_WARN_PCAP_MULTI_DEV_EXPERIMENTAL);
CASE_CODE (SC_ERR_PCAP_MULTI_DEV_NO_SUPPORT);
default:
return "UNKNOWN_ERROR";

@ -203,6 +203,8 @@ typedef enum {
SC_ERR_DETECT_PREPARE, /**< preparing the detection engine failed */
SC_ERR_AHO_CORASICK,
SC_ERR_REFERENCE_CONFIG,
SC_WARN_PCAP_MULTI_DEV_EXPERIMENTAL,
SC_ERR_PCAP_MULTI_DEV_NO_SUPPORT,
} SCError;
const char *SCErrorToString(SCError);

Loading…
Cancel
Save