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) { int RunModeIdsPcapAuto(DetectEngineCtx *de_ctx, char *iface) {
SCEnter(); SCEnter();
/* tname = Detect + cpuid, this is 11bytes length as max */ /* tname = Detect + cpuid, this is 11bytes length as max */
char tname[12]; char tname[16];
uint16_t cpu = 0; uint16_t cpu = 0;
TmModule *tm_module;
uint16_t thread;
RunModeInitialize(); RunModeInitialize();
TimeModeSetLive();
/* Available cpus */ /* Available cpus */
uint16_t ncpus = UtilCpuGetNumProcessorsOnline(); uint16_t ncpus = UtilCpuGetNumProcessorsOnline();
int npcap = PcapLiveGetDeviceCount();
TimeModeSetLive(); if (npcap == 1) {
/* create the threads */ /* create the threads */
ThreadVars *tv_receivepcap = TmThreadCreatePacketHandler("ReceivePcap","packetpool","packetpool","pickup-queue","simple","1slot"); ThreadVars *tv_receivepcap = TmThreadCreatePacketHandler("ReceivePcap","packetpool","packetpool","pickup-queue","simple","1slot");
if (tv_receivepcap == NULL) { if (tv_receivepcap == NULL) {
printf("ERROR: TmThreadsCreate failed\n"); printf("ERROR: TmThreadsCreate failed\n");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
TmModule *tm_module = TmModuleGetByName("ReceivePcap"); tm_module = TmModuleGetByName("ReceivePcap");
if (tm_module == NULL) { if (tm_module == NULL) {
printf("ERROR: TmModuleGetByName failed for ReceivePcap\n"); printf("ERROR: TmModuleGetByName failed for ReceivePcap\n");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
Tm1SlotSetFunc(tv_receivepcap,tm_module,(void *)iface); Tm1SlotSetFunc(tv_receivepcap,tm_module,(void *)iface);
if (threading_set_cpu_affinity) { if (threading_set_cpu_affinity) {
TmThreadSetCPUAffinity(tv_receivepcap, 0); TmThreadSetCPUAffinity(tv_receivepcap, 0);
if (ncpus > 1) if (ncpus > 1)
TmThreadSetThreadPriority(tv_receivepcap, PRIO_MEDIUM); 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) { for (thread = 0; thread < npcap; thread++) {
printf("ERROR: TmThreadSpawn failed\n"); char *pcap_dev = PcapLiveGetDevice(thread);
exit(EXIT_FAILURE); 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__) #if defined(__SC_CUDA_SUPPORT__)
@ -2265,7 +2308,6 @@ int RunModeIdsPcapAuto(DetectEngineCtx *de_ctx, char *iface) {
if (thread_max < 1) if (thread_max < 1)
thread_max = 1; thread_max = 1;
int thread;
for (thread = 0; thread < thread_max; thread++) { for (thread = 0; thread < thread_max; thread++) {
snprintf(tname, sizeof(tname),"Detect%"PRIu16, thread+1); snprintf(tname, sizeof(tname),"Detect%"PRIu16, thread+1);
if (tname == NULL) if (tname == NULL)

@ -48,8 +48,19 @@
extern uint8_t suricata_ctl_flags; extern uint8_t suricata_ctl_flags;
extern int max_pending_packets; extern int max_pending_packets;
/** control how many packet libpcap may read in one go */
static int pcap_max_read_packets = 0; 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 */ /** max packets < 65536 */
#define PCAP_FILE_MAX_PKTS 256 #define PCAP_FILE_MAX_PKTS 256
@ -521,6 +532,66 @@ TmEcode DecodePcapThreadInit(ThreadVars *tv, void *initdata, void **data)
SCReturnInt(TM_ECODE_OK); 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) void PcapTranslateIPToDevice(char *pcap_dev, size_t len)
{ {
char errbuf[PCAP_ERRBUF_SIZE]; char errbuf[PCAP_ERRBUF_SIZE];

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

@ -638,6 +638,17 @@ int main(int argc, char **argv)
case 'i': case 'i':
if (run_mode == MODE_UNKNOWN) { if (run_mode == MODE_UNKNOWN) {
run_mode = MODE_PCAP_DEV; 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 { } else {
SCLogError(SC_ERR_MULTIPLE_RUN_MODE, "more than one run mode " SCLogError(SC_ERR_MULTIPLE_RUN_MODE, "more than one run mode "
"has been specified"); "has been specified");
@ -645,7 +656,7 @@ int main(int argc, char **argv)
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
memset(pcap_dev, 0, sizeof(pcap_dev)); 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; break;
case 'l': case 'l':
if (ConfSet("default-log-dir", optarg, 0) != 1) { 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_DCERPC);
CASE_CODE (SC_ERR_AHO_CORASICK); CASE_CODE (SC_ERR_AHO_CORASICK);
CASE_CODE (SC_ERR_REFERENCE_CONFIG); CASE_CODE (SC_ERR_REFERENCE_CONFIG);
CASE_CODE (SC_WARN_PCAP_MULTI_DEV_EXPERIMENTAL);
CASE_CODE (SC_ERR_PCAP_MULTI_DEV_NO_SUPPORT);
default: default:
return "UNKNOWN_ERROR"; return "UNKNOWN_ERROR";

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

Loading…
Cancel
Save