}
/**
- * \brief Add a Netfilter queue
+ * \brief Add a single Netfilter queue
*
- * \param string with the queue name
+ * \param string with the queue number
*
* \retval 0 on success.
* \retval -1 on failure.
*/
-int NFQRegisterQueue(char *queue)
+int NFQRegisterQueue(const uint16_t number)
{
NFQThreadVars *ntv = NULL;
NFQQueueVars *nq = NULL;
- /* Extract the queue number from the specified command line argument */
- uint16_t queue_num = 0;
- if ((ByteExtractStringUint16(&queue_num, 10, strlen(queue), queue)) < 0)
- {
- SCLogError(SC_ERR_INVALID_ARGUMENT, "specified queue number %s is not "
- "valid", queue);
- return -1;
- }
+ char queue[6] = { 0 };
SCMutexLock(&nfq_init_lock);
if (receive_queue_num >= NFQ_MAX_QUEUE) {
ntv->nfq_index = receive_queue_num;
nq = &g_nfq_q[receive_queue_num];
- nq->queue_num = queue_num;
+ nq->queue_num = number;
receive_queue_num++;
SCMutexUnlock(&nfq_init_lock);
+ snprintf(queue, sizeof(queue) - 1, "%hu", number);
LiveRegisterDeviceName(queue);
- SCLogDebug("Queue \"%s\" registered.", queue);
+ SCLogDebug("Queue %d registered.", number);
return 0;
}
+/**
+ * \brief Parses and adds Netfilter queue(s).
+ *
+ * \param string with the queue number or range
+ *
+ * \retval 0 on success.
+ * \retval -1 on failure.
+ */
+int NFQParseAndRegisterQueues(const char *queues)
+{
+ uint16_t queue_start = 0;
+ uint16_t queue_end = 0;
+
+ // Either "id" or "start:end" format (e.g., "12" or "0:5")
+ int count = sscanf(queues, "%hu:%hu", &queue_start, &queue_end);
+
+ if (count < 1) {
+ SCLogError(SC_ERR_INVALID_ARGUMENT, "specified queue(s) argument '%s' is not "
+ "valid (allowed queue numbers are 0-65535)", queues);
+ return -1;
+ }
+
+ // Do we have a range?
+ if (count == 2) {
+ // Sanity check
+ if (queue_start > queue_end) {
+ SCLogError(SC_ERR_INVALID_ARGUMENT, "start queue's number %d is greater than "
+ "ending number %d", queue_start, queue_end);
+ return -1;
+ }
+
+ for (uint16_t i = queue_start; i <= queue_end; i++) {
+ if (NFQRegisterQueue(i) != 0) {
+ return -1;
+ }
+ }
+ } else if (NFQRegisterQueue(queue_start) != 0) {
+ SCLogError(SC_ERR_INVALID_ARGUMENT, "queue(s) argument '%s' is not "
+ "valid", queues);
+ return -1;
+ }
+ return 0;
+}
/**
* \brief Get a pointer to the NFQ queue at index
printf("\t-F <bpf filter file> : bpf filter file\n");
printf("\t-r <path> : run in pcap file/offline mode\n");
#ifdef NFQ
- printf("\t-q <qid> : run in inline nfqueue mode\n");
+ printf("\t-q <qid[:qid]> : run in inline nfqueue mode (use colon to specify a range of queues)\n");
#endif /* NFQ */
#ifdef IPFW
printf("\t-d <divert port> : run in inline ipfw divert mode\n");
if (suri->run_mode == RUNMODE_UNKNOWN) {
suri->run_mode = RUNMODE_NFQ;
EngineModeSetIPS();
- if (NFQRegisterQueue(optarg) == -1)
+ if (NFQParseAndRegisterQueues(optarg) == -1)
return TM_ECODE_FAILED;
} else if (suri->run_mode == RUNMODE_NFQ) {
- if (NFQRegisterQueue(optarg) == -1)
+ if (NFQParseAndRegisterQueues(optarg) == -1)
return TM_ECODE_FAILED;
} else {
SCLogError(SC_ERR_MULTIPLE_RUN_MODE, "more than one run mode "