]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
source-nfq: support queue range
authorAlexander Gozman <a.gozman@securitycode.ru>
Tue, 6 Nov 2018 18:09:21 +0000 (18:09 +0000)
committerVictor Julien <victor@inliniac.net>
Fri, 8 Feb 2019 06:26:23 +0000 (07:26 +0100)
If one needs to use multiple sequential Netfilter queues,
it can be done with a new '-q' option's syntax: "start:end"
(just like it's done with iptables '--queue-balance' option).

src/source-nfq.c
src/source-nfq.h
src/suricata.c

index 81886f4ea373281d9fd72f5f2e912aee199b7ce2..d1c4c856a418bc6d5397e99e4276dd2f7d4db5be 100644 (file)
@@ -816,25 +816,18 @@ TmEcode VerdictNFQThreadDeinit(ThreadVars *tv, void *data)
 }
 
 /**
- *  \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) {
@@ -853,16 +846,60 @@ int NFQRegisterQueue(char *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
index 374b3332bbae2e7fb1a7b51038657538d8792194..d7d59435cb49c4ed078037af270b97b4f406b49f 100644 (file)
@@ -89,7 +89,8 @@ typedef struct NFQGlobalVars_
 } NFQGlobalVars;
 
 void NFQInitConfig(char quiet);
-int NFQRegisterQueue(char *queue);
+int NFQRegisterQueue(const uint16_t number);
+int NFQParseAndRegisterQueues(const char *queues);
 int NFQGetQueueCount(void);
 void *NFQGetQueue(int number);
 int NFQGetQueueNum(int number);
index b6aaa56260817521d8f3088092a1c428516b840b..05547f43c000ae657a9c9418e8107d96eaac4d50 100644 (file)
@@ -582,7 +582,7 @@ static void PrintUsage(const char *progname)
     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");
@@ -1974,10 +1974,10 @@ static TmEcode ParseCommandLine(int argc, char** argv, SCInstance *suri)
             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 "