]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
reject: allow configuration of the reject interface
authorVictor Julien <victor@inliniac.net>
Thu, 11 Jun 2020 09:27:29 +0000 (11:27 +0200)
committerVictor Julien <victor@inliniac.net>
Sun, 28 Jun 2020 13:20:56 +0000 (15:20 +0200)
Using the '--reject-dev <dev>' commandline option. This is a global option
that applies to all 'reject' actions.

If the interface specified is using ethernet, libnet will use the faster
L2 (link) layer. Suricata sets up the ethernet header based on the packet.

When the interface is specified, cache libnet_t ctx for (much) better
performance.

src/respond-reject-libnet11.c
src/respond-reject-libnet11.h
src/respond-reject.c
src/runmode-af-packet.c
src/runmode-pcap.c
src/suricata.c

index 0e15fe47fe36771a41174a2d25d6defa84cb0649..a4f3ab1ab7a40a57819accdccd1d54e07e09d1f1 100644 (file)
 #define LIBNET_INIT_CAST
 #endif
 
+/* Globally configured device to use for sending resets in IDS mode. */
+const char *g_reject_dev = NULL;
+
 /** set to true in main if we're setting caps. We need it here if we're using
   * reject rules as libnet 1.1 is not compatible with caps. */
 extern int sc_set_caps;
 
 #include <libnet.h>
 
-extern uint8_t host_mode;
+thread_local libnet_t *t_c = NULL;
+thread_local int t_inject_mode = -1;
 
 typedef struct Libnet11Packet_ {
     uint32_t ack, seq;
@@ -76,38 +80,59 @@ typedef struct Libnet11Packet_ {
     uint32_t src4, dst4;
     uint16_t sp, dp;
     size_t len;
+    uint8_t *smac, *dmac;
 } Libnet11Packet;
 
-int RejectSendLibnet11L3IPv4TCP(ThreadVars *tv, Packet *p, void *data, int dir)
+static inline libnet_t *GetCtx(const Packet *p, int injection_type)
 {
-    Libnet11Packet lpacket;
-    libnet_t *c; /* libnet context */
-    char ebuf[LIBNET_ERRBUF_SIZE];
-    int result;
-    const char *devname = NULL;
-
-    /* fill in struct defaults */
-    lpacket.ttl = 0;
-    lpacket.id = 0;
-    lpacket.flow = 0;
-    lpacket.class = 0;
+    /* fast path: use cache ctx */
+    if (t_c)
+        return t_c;
 
-    if (IS_SURI_HOST_MODE_SNIFFER_ONLY(host_mode) && (p->livedev)) {
-        devname = p->livedev->dev;
-        SCLogDebug("Will emit reject packet on dev %s", devname);
+    /* slow path: setup a new ctx */
+    bool store_ctx = false;
+    const char *devname = NULL;
+    extern uint8_t host_mode;
+    if (IS_SURI_HOST_MODE_SNIFFER_ONLY(host_mode)) {
+        if (g_reject_dev != NULL) {
+            if (p->datalink == LINKTYPE_ETHERNET)
+                injection_type = t_inject_mode = LIBNET_LINK;
+            devname = g_reject_dev;
+            store_ctx = true;
+        } else {
+            devname = p->livedev ? p->livedev->dev : NULL;
+        }
     }
 
-    if (p->tcph == NULL)
-        return 1;
-
-    if ((c = libnet_init(LIBNET_RAW4, LIBNET_INIT_CAST devname, ebuf)) == NULL) {
+    char ebuf[LIBNET_ERRBUF_SIZE];
+    libnet_t *c = libnet_init(injection_type, LIBNET_INIT_CAST devname, ebuf);
+    if (c == NULL) {
         SCLogError(SC_ERR_LIBNET_INIT,"libnet_init failed: %s", ebuf);
-        return 1;
     }
+    if (store_ctx) {
+        t_c = c;
+    }
+    return c;
+}
 
-    /* save payload len */
-    lpacket.dsize = p->payload_len;
+static inline void ClearCtx(libnet_t *c)
+{
+    if (t_c == c)
+        libnet_clear_packet(c);
+    else
+        libnet_destroy(c);
+}
 
+void FreeCachedCtx(void)
+{
+    if (t_c) {
+        libnet_destroy(t_c);
+        t_c = NULL;
+    }
+}
+
+static inline void SetupTCP(Packet *p, Libnet11Packet *lpacket, int dir)
+{
     switch (dir) {
         case REJECT_DIR_SRC:
             SCLogDebug("sending a tcp reset to src");
@@ -117,50 +142,41 @@ int RejectSendLibnet11L3IPv4TCP(ThreadVars *tv, Packet *p, void *data, int dir)
              *  is equal to the ACK of incoming packet and the ACK is build
              *  using packet sequence number and size of the data. */
             if (TCP_GET_ACK(p) == 0) {
-                lpacket.seq = 0;
-                lpacket.ack = TCP_GET_SEQ(p) + lpacket.dsize + 1;
+                lpacket->seq = 0;
+                lpacket->ack = TCP_GET_SEQ(p) + lpacket->dsize + 1;
             } else {
-                lpacket.seq = TCP_GET_ACK(p);
-                lpacket.ack = TCP_GET_SEQ(p) + lpacket.dsize;
+                lpacket->seq = TCP_GET_ACK(p);
+                lpacket->ack = TCP_GET_SEQ(p) + lpacket->dsize;
             }
 
-            lpacket.sp = TCP_GET_DST_PORT(p);
-            lpacket.dp = TCP_GET_SRC_PORT(p);
-
-            lpacket.src4 = GET_IPV4_DST_ADDR_U32(p);
-            lpacket.dst4 = GET_IPV4_SRC_ADDR_U32(p);
+            lpacket->sp = TCP_GET_DST_PORT(p);
+            lpacket->dp = TCP_GET_SRC_PORT(p);
             break;
         case REJECT_DIR_DST:
             SCLogDebug("sending a tcp reset to dst");
-            lpacket.seq = TCP_GET_SEQ(p);
-            lpacket.ack = TCP_GET_ACK(p);
-
-            lpacket.sp = TCP_GET_SRC_PORT(p);
-            lpacket.dp = TCP_GET_DST_PORT(p);
+            lpacket->seq = TCP_GET_SEQ(p);
+            lpacket->ack = TCP_GET_ACK(p);
 
-            lpacket.src4 = GET_IPV4_SRC_ADDR_U32(p);
-            lpacket.dst4 = GET_IPV4_DST_ADDR_U32(p);
+            lpacket->sp = TCP_GET_SRC_PORT(p);
+            lpacket->dp = TCP_GET_DST_PORT(p);
             break;
         default:
-            SCLogError(SC_ERR_LIBNET_INVALID_DIR,
-                       "reset not src or dst returning");
-            return 1;
+            abort();
     }
-
-    lpacket.window = TCP_GET_WINDOW(p);
+    lpacket->window = TCP_GET_WINDOW(p);
     //lpacket.seq += lpacket.dsize;
+}
 
-    /* TODO come up with ttl calc function */
-    lpacket.ttl = 64;
-
+static inline int BuildTCP(libnet_t *c, Libnet11Packet *lpacket)
+{
     /* build the package */
     if ((libnet_build_tcp(
-                    lpacket.sp,            /* source port */
-                    lpacket.dp,            /* dst port */
-                    lpacket.seq,           /* seq number */
-                    lpacket.ack,           /* ack number */
+                    lpacket->sp,           /* source port */
+                    lpacket->dp,           /* dst port */
+                    lpacket->seq,          /* seq number */
+                    lpacket->ack,          /* ack number */
                     TH_RST|TH_ACK,         /* flags */
-                    lpacket.window,        /* window size */
+                    lpacket->window,       /* window size */
                     0,                     /* checksum */
                     0,                     /* urgent flag */
                     LIBNET_TCP_H,          /* header length */
@@ -170,26 +186,129 @@ int RejectSendLibnet11L3IPv4TCP(ThreadVars *tv, Packet *p, void *data, int dir)
                     0)) < 0)               /* libnet ptag */
     {
         SCLogError(SC_ERR_LIBNET_BUILD_FAILED,"libnet_build_tcp %s", libnet_geterror(c));
-        goto cleanup;
+        return -1;
     }
+    return 0;
+}
 
+static inline int BuildIPv4(libnet_t *c, Libnet11Packet *lpacket, const uint8_t proto)
+{
+    const int len = LIBNET_IPV4_H + lpacket->len +
+        ((proto == IPPROTO_TCP) ? LIBNET_TCP_H : LIBNET_ICMPV4_H);
     if ((libnet_build_ipv4(
-                    LIBNET_TCP_H + LIBNET_IPV4_H, /* entire packet length */
+                    len,                          /* entire packet length */
                     0,                            /* tos */
-                    lpacket.id,                   /* ID */
+                    lpacket->id,                  /* ID */
                     0,                            /* fragmentation flags and offset */
-                    lpacket.ttl,                  /* TTL */
-                    IPPROTO_TCP,                  /* protocol */
+                    lpacket->ttl,                 /* TTL */
+                    proto,                        /* protocol */
                     0,                            /* checksum */
-                    lpacket.src4,                 /* source address */
-                    lpacket.dst4,                 /* destination address */
+                    lpacket->src4,                /* source address */
+                    lpacket->dst4,                /* destination address */
                     NULL,                         /* pointer to packet data (or NULL) */
                     0,                            /* payload length */
                     c,                            /* libnet context pointer */
                     0)) < 0)                      /* packet id */
     {
         SCLogError(SC_ERR_LIBNET_BUILD_FAILED,"libnet_build_ipv4 %s", libnet_geterror(c));
+        return -1;
+    }
+    return 0;
+}
+
+static inline int BuildIPv6(libnet_t *c, Libnet11Packet *lpacket, const uint8_t proto)
+{
+    const int len = lpacket->len +
+        ((proto == IPPROTO_TCP) ? LIBNET_TCP_H : LIBNET_ICMPV6_H);
+    if ((libnet_build_ipv6(
+                    lpacket->class,               /* traffic class */
+                    lpacket->flow,                /* Flow label */
+                    len,                          /* payload length */
+                    proto,                        /* next header */
+                    lpacket->ttl,                 /* TTL */
+                    lpacket->src6,                /* source address */
+                    lpacket->dst6,                /* destination address */
+                    NULL,                         /* pointer to packet data (or NULL) */
+                    0,                            /* payload length */
+                    c,                            /* libnet context pointer */
+                    0)) < 0)                      /* packet id */
+    {
+        SCLogError(SC_ERR_LIBNET_BUILD_FAILED,"libnet_build_ipv6 %s", libnet_geterror(c));
+        return -1;
+    }
+    return 0;
+}
+
+static inline void SetupEthernet(Packet *p, Libnet11Packet *lpacket, int dir)
+{
+    switch (dir) {
+        case REJECT_DIR_SRC:
+            lpacket->smac = p->ethh->eth_dst;
+            lpacket->dmac = p->ethh->eth_src;
+            break;
+        case REJECT_DIR_DST:
+            lpacket->smac = p->ethh->eth_src;
+            lpacket->dmac = p->ethh->eth_dst;
+            break;
+        default:
+            abort();
+    }
+}
+static inline int BuildEthernet(libnet_t *c, Libnet11Packet *lpacket, uint16_t proto)
+{
+    if ((libnet_build_ethernet(lpacket->dmac,lpacket->smac, proto , NULL, 0, c, 0)) < 0) {
+        SCLogError(SC_ERR_LIBNET_BUILD_FAILED,"libnet_build_ethernet %s", libnet_geterror(c));
+        return -1;
+    }
+    return 0;
+}
+
+int RejectSendLibnet11L3IPv4TCP(ThreadVars *tv, Packet *p, void *data, int dir)
+{
+    Libnet11Packet lpacket;
+    int result;
+
+    /* fill in struct defaults */
+    lpacket.ttl = 0;
+    lpacket.id = 0;
+    lpacket.flow = 0;
+    lpacket.class = 0;
+
+    if (p->tcph == NULL)
+        return 1;
+
+    libnet_t *c = GetCtx(p, LIBNET_RAW4);
+    if (c == NULL)
+        return 1;
+
+    /* save payload len */
+    lpacket.dsize = p->payload_len;
+
+    switch (dir) {
+        case REJECT_DIR_SRC:
+            lpacket.src4 = GET_IPV4_DST_ADDR_U32(p);
+            lpacket.dst4 = GET_IPV4_SRC_ADDR_U32(p);
+            break;
+        case REJECT_DIR_DST:
+            lpacket.src4 = GET_IPV4_SRC_ADDR_U32(p);
+            lpacket.dst4 = GET_IPV4_DST_ADDR_U32(p);
+            break;
+    }
+    /* TODO come up with ttl calc function */
+    lpacket.ttl = 64;
+
+    SetupTCP(p, &lpacket, dir);
+
+    if (BuildTCP(c, &lpacket) < 0)
+        goto cleanup;
+
+    if (BuildIPv4(c, &lpacket, IPPROTO_TCP) < 0)
         goto cleanup;
+
+    if (t_inject_mode == LIBNET_LINK) {
+        SetupEthernet(p, &lpacket, dir);
+        if (BuildEthernet(c, &lpacket, ETHERNET_TYPE_IP) < 0)
+            goto cleanup;
     }
 
     result = libnet_write(c);
@@ -199,17 +318,14 @@ int RejectSendLibnet11L3IPv4TCP(ThreadVars *tv, Packet *p, void *data, int dir)
     }
 
 cleanup:
-    libnet_destroy (c);
+    ClearCtx(c);
     return 0;
 }
 
 int RejectSendLibnet11L3IPv4ICMP(ThreadVars *tv, Packet *p, void *data, int dir)
 {
     Libnet11Packet lpacket;
-    libnet_t *c; /* libnet context */
-    char ebuf[LIBNET_ERRBUF_SIZE];
     int result;
-    const char *devname = NULL;
 
     /* fill in struct defaults */
     lpacket.ttl = 0;
@@ -218,13 +334,9 @@ int RejectSendLibnet11L3IPv4ICMP(ThreadVars *tv, Packet *p, void *data, int dir)
     lpacket.class = 0;
     lpacket.len = (IPV4_GET_HLEN(p) + p->payload_len);
 
-    if (IS_SURI_HOST_MODE_SNIFFER_ONLY(host_mode) && (p->livedev)) {
-        devname = p->livedev->dev;
-    }
-    if ((c = libnet_init(LIBNET_RAW4, LIBNET_INIT_CAST devname, ebuf)) == NULL) {
-        SCLogError(SC_ERR_LIBNET_INIT,"libnet_inint failed: %s", ebuf);
+    libnet_t *c = GetCtx(p, LIBNET_RAW4);
+    if (c == NULL)
         return 1;
-    }
 
     switch (dir) {
         case REJECT_DIR_SRC:
@@ -258,24 +370,13 @@ int RejectSendLibnet11L3IPv4ICMP(ThreadVars *tv, Packet *p, void *data, int dir)
         goto cleanup;
     }
 
-    if ((libnet_build_ipv4(
-                    LIBNET_ICMPV4_H + LIBNET_IPV4_H +
-                    lpacket.len,                    /* entire packet length */
-                    0,                              /* tos */
-                    lpacket.id,                     /* ID */
-                    0,                              /* fragmentation flags and offset */
-                    lpacket.ttl,                    /* TTL */
-                    IPPROTO_ICMP,                   /* protocol */
-                    0,                              /* checksum */
-                    lpacket.src4,                   /* source address */
-                    lpacket.dst4,                   /* destination address */
-                    NULL,                           /* pointer to packet data (or NULL) */
-                    0,                              /* payload length */
-                    c,                              /* libnet context pointer */
-                    0)) < 0)                        /* packet id */
-    {
-        SCLogError(SC_ERR_LIBNET_BUILD_FAILED,"libnet_build_ipv4 %s", libnet_geterror(c));
+    if (BuildIPv4(c, &lpacket, IPPROTO_ICMP) < 0)
         goto cleanup;
+
+    if (t_inject_mode == LIBNET_LINK) {
+        SetupEthernet(p, &lpacket, dir);
+        if (BuildEthernet(c, &lpacket, ETHERNET_TYPE_IP) < 0)
+            goto cleanup;
     }
 
     result = libnet_write(c);
@@ -285,17 +386,14 @@ int RejectSendLibnet11L3IPv4ICMP(ThreadVars *tv, Packet *p, void *data, int dir)
     }
 
 cleanup:
-    libnet_destroy (c);
+    ClearCtx(c);
     return 0;
 }
 
 int RejectSendLibnet11L3IPv6TCP(ThreadVars *tv, Packet *p, void *data, int dir)
 {
     Libnet11Packet lpacket;
-    libnet_t *c; /* libnet context */
-    char ebuf[LIBNET_ERRBUF_SIZE];
     int result;
-    const char *devname = NULL;
 
     /* fill in struct defaults */
     lpacket.ttl = 0;
@@ -303,102 +401,40 @@ int RejectSendLibnet11L3IPv6TCP(ThreadVars *tv, Packet *p, void *data, int dir)
     lpacket.flow = 0;
     lpacket.class = 0;
 
-    if (IS_SURI_HOST_MODE_SNIFFER_ONLY(host_mode) && (p->livedev)) {
-        devname = p->livedev->dev;
-    }
-
     if (p->tcph == NULL)
        return 1;
 
-    if ((c = libnet_init(LIBNET_RAW6, LIBNET_INIT_CAST devname, ebuf)) == NULL) {
-        SCLogError(SC_ERR_LIBNET_INIT,"libnet_init failed: %s", ebuf);
+    libnet_t *c = GetCtx(p, LIBNET_RAW6);
+    if (c == NULL)
         return 1;
-    }
 
     /* save payload len */
     lpacket.dsize = p->payload_len;
 
     switch (dir) {
         case REJECT_DIR_SRC:
-            SCLogDebug("sending a tcp reset to src");
-            /* We follow http://tools.ietf.org/html/rfc793#section-3.4 :
-             *  If packet has no ACK, the seq number is 0 and the ACK is built
-             *  the normal way. If packet has a ACK, the seq of the RST packet
-             *  is equal to the ACK of incoming packet and the ACK is build
-             *  using packet sequence number and size of the data. */
-            if (TCP_GET_ACK(p) == 0) {
-                lpacket.seq = 0;
-                lpacket.ack = TCP_GET_SEQ(p) + lpacket.dsize + 1;
-            } else {
-                lpacket.seq = TCP_GET_ACK(p);
-                lpacket.ack = TCP_GET_SEQ(p) + lpacket.dsize;
-            }
-
-            lpacket.sp = TCP_GET_DST_PORT(p);
-            lpacket.dp = TCP_GET_SRC_PORT(p);
-
             memcpy(lpacket.src6.libnet_s6_addr, GET_IPV6_DST_ADDR(p), 16);
             memcpy(lpacket.dst6.libnet_s6_addr, GET_IPV6_SRC_ADDR(p), 16);
-
             break;
         case REJECT_DIR_DST:
-            SCLogDebug("sending a tcp reset to dst");
-            lpacket.seq = TCP_GET_SEQ(p);
-            lpacket.ack = TCP_GET_ACK(p);
-
-            lpacket.sp = TCP_GET_SRC_PORT(p);
-            lpacket.dp = TCP_GET_DST_PORT(p);
-
             memcpy(lpacket.src6.libnet_s6_addr, GET_IPV6_SRC_ADDR(p), 16);
             memcpy(lpacket.dst6.libnet_s6_addr, GET_IPV6_DST_ADDR(p), 16);
             break;
-        default:
-            SCLogError(SC_ERR_LIBNET_INVALID_DIR,
-                       "reset not src or dst returning");
-            return 1;
     }
-
-    lpacket.window = TCP_GET_WINDOW(p);
-    //lpacket.seq += lpacket.dsize;
-
     /* TODO come up with ttl calc function */
     lpacket.ttl = 64;
 
-    /* build the package */
-    if ((libnet_build_tcp(
-                    lpacket.sp,            /* source port */
-                    lpacket.dp,            /* dst port */
-                    lpacket.seq,           /* seq number */
-                    lpacket.ack,           /* ack number */
-                    TH_RST|TH_ACK,         /* flags */
-                    lpacket.window,        /* window size */
-                    0,                     /* checksum */
-                    0,                     /* urgent flag */
-                    LIBNET_TCP_H,          /* header length */
-                    NULL,                  /* payload */
-                    0,                     /* payload length */
-                    c,                     /* libnet context */
-                    0)) < 0)               /* libnet ptag */
-    {
-        SCLogError(SC_ERR_LIBNET_BUILD_FAILED,"libnet_build_tcp %s", libnet_geterror(c));
-        goto cleanup;
-    }
+    SetupTCP(p, &lpacket, dir);
 
-    if ((libnet_build_ipv6(
-                    lpacket.class,                /* traffic class */
-                    lpacket.flow,                 /* Flow label */
-                    LIBNET_TCP_H,                 /* payload length */
-                    IPPROTO_TCP,                  /* next header */
-                    lpacket.ttl,                  /* TTL */
-                    lpacket.src6,                 /* source address */
-                    lpacket.dst6,                 /* destination address */
-                    NULL,                         /* pointer to packet data (or NULL) */
-                    0,                            /* payload length */
-                    c,                            /* libnet context pointer */
-                    0)) < 0)                      /* packet id */
-    {
-        SCLogError(SC_ERR_LIBNET_BUILD_FAILED,"libnet_build_ipv6 %s", libnet_geterror(c));
+    BuildTCP(c, &lpacket);
+
+    if (BuildIPv6(c, &lpacket, IPPROTO_ICMP) < 0)
         goto cleanup;
+
+    if (t_inject_mode == LIBNET_LINK) {
+        SetupEthernet(p, &lpacket, dir);
+        if (BuildEthernet(c, &lpacket, ETHERNET_TYPE_IPV6) < 0)
+            goto cleanup;
     }
 
     result = libnet_write(c);
@@ -408,7 +444,7 @@ int RejectSendLibnet11L3IPv6TCP(ThreadVars *tv, Packet *p, void *data, int dir)
     }
 
 cleanup:
-    libnet_destroy (c);
+    ClearCtx(c);
     return 0;
 }
 
@@ -416,10 +452,7 @@ cleanup:
 int RejectSendLibnet11L3IPv6ICMP(ThreadVars *tv, Packet *p, void *data, int dir)
 {
     Libnet11Packet lpacket;
-    libnet_t *c; /* libnet context */
-    char ebuf[LIBNET_ERRBUF_SIZE];
     int result;
-    const char *devname = NULL;
 
     /* fill in struct defaults */
     lpacket.ttl = 0;
@@ -428,13 +461,9 @@ int RejectSendLibnet11L3IPv6ICMP(ThreadVars *tv, Packet *p, void *data, int dir)
     lpacket.class = 0;
     lpacket.len = IPV6_GET_PLEN(p) + IPV6_HEADER_LEN;
 
-    if (IS_SURI_HOST_MODE_SNIFFER_ONLY(host_mode) && (p->livedev)) {
-        devname = p->livedev->dev;
-    }
-    if ((c = libnet_init(LIBNET_RAW6, LIBNET_INIT_CAST devname, ebuf)) == NULL) {
-        SCLogError(SC_ERR_LIBNET_INIT,"libnet_inint failed: %s", ebuf);
+    libnet_t *c = GetCtx(p, LIBNET_RAW6);
+    if (c == NULL)
         return 1;
-    }
 
     switch (dir) {
         case REJECT_DIR_SRC:
@@ -468,21 +497,13 @@ int RejectSendLibnet11L3IPv6ICMP(ThreadVars *tv, Packet *p, void *data, int dir)
         goto cleanup;
     }
 
-    if ((libnet_build_ipv6(
-                    lpacket.class,                            /* traffic class */
-                    lpacket.flow,                            /* Flow label */
-                    LIBNET_ICMPV6_H + lpacket.len, /* IPv6 payload length */
-                    IPPROTO_ICMPV6,               /* next header */
-                    lpacket.ttl,                  /* TTL */
-                    lpacket.src6,                 /* source address */
-                    lpacket.dst6,                 /* destination address */
-                    NULL,                         /* pointer to packet data (or NULL) */
-                    0,                            /* payload length */
-                    c,                            /* libnet context pointer */
-                    0)) < 0)                      /* packet id */
-    {
-        SCLogError(SC_ERR_LIBNET_BUILD_FAILED,"libnet_build_ipv6 %s", libnet_geterror(c));
+    if (BuildIPv6(c, &lpacket, IPPROTO_ICMP) < 0)
         goto cleanup;
+
+    if (t_inject_mode == LIBNET_LINK) {
+        SetupEthernet(p, &lpacket, dir);
+        if (BuildEthernet(c, &lpacket, ETHERNET_TYPE_IPV6) < 0)
+            goto cleanup;
     }
 
     result = libnet_write(c);
@@ -492,9 +513,10 @@ int RejectSendLibnet11L3IPv6ICMP(ThreadVars *tv, Packet *p, void *data, int dir)
     }
 
 cleanup:
-    libnet_destroy (c);
+    ClearCtx(c);
     return 0;
 }
+
 #else /* HAVE_LIBNET_ICMPV6_UNREACH */
 
 int RejectSendLibnet11L3IPv6ICMP(ThreadVars *tv, Packet *p, void *data, int dir)
@@ -541,4 +563,9 @@ int RejectSendLibnet11L3IPv6ICMP(ThreadVars *tv, Packet *p, void *data, int dir)
     return 0;
 }
 
+void FreeCachedCtx(void)
+{
+    SCLogDebug("no libhnet support");
+}
+
 #endif /* HAVE_LIBNET11 */
index 06fdde45f44405b559c15a7c410bb193061a938f..f7ffab98b7850c2eb82b0ce87d8df853a7408643 100644 (file)
@@ -31,4 +31,6 @@ int RejectSendLibnet11L3IPv4ICMP(ThreadVars *, Packet *, void *,int);
 int RejectSendLibnet11L3IPv6TCP(ThreadVars *, Packet *, void *,int);
 int RejectSendLibnet11L3IPv6ICMP(ThreadVars *, Packet *, void *,int);
 
+void FreeCachedCtx(void);
+
 #endif /* __RESPOND_REJECT_LIBNET11_H__ */
index 6f054fc8ae6a3ae8eee46c82e715bd9b7e683a8f..b454f61060fbd7fb4eb9d8429c071943c86f2ce6 100644 (file)
@@ -44,17 +44,24 @@ int RejectSendIPv4ICMP(ThreadVars *, Packet *, void *);
 int RejectSendIPv6TCP(ThreadVars *, Packet *, void *);
 int RejectSendIPv6ICMP(ThreadVars *, Packet *, void *);
 static TmEcode RespondRejectFunc(ThreadVars *tv, Packet *p, void *data);
+static TmEcode RespondRejectThreadDeinit(ThreadVars *tv, void *data);
 
 void TmModuleRespondRejectRegister (void)
 {
     tmm_modules[TMM_RESPONDREJECT].name = "RespondReject";
     tmm_modules[TMM_RESPONDREJECT].ThreadInit = NULL;
     tmm_modules[TMM_RESPONDREJECT].Func = RespondRejectFunc;
-    tmm_modules[TMM_RESPONDREJECT].ThreadDeinit = NULL;
+    tmm_modules[TMM_RESPONDREJECT].ThreadDeinit = RespondRejectThreadDeinit;
     tmm_modules[TMM_RESPONDREJECT].RegisterTests = NULL;
     tmm_modules[TMM_RESPONDREJECT].cap_flags = 0; /* libnet is not compat with caps */
 }
 
+static TmEcode RespondRejectThreadDeinit(ThreadVars *tv, void *data)
+{
+    FreeCachedCtx();
+    return TM_ECODE_OK;
+}
+
 static TmEcode RespondRejectFunc(ThreadVars *tv, Packet *p, void *data)
 {
     /* ACTION_REJECT defaults to rejecting the SRC */
index f7b2647b804233a6817c6d1149d723d94ea7e3db..8143b43b00735aec4db72448f3dbc9003ba03f15 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (C) 2011-2016 Open Information Security Foundation
+/* Copyright (C) 2011-2020 Open Information Security Foundation
  *
  * You can copy, redistribute or modify this Program under the terms of
  * the GNU General Public License version 2 as published by the Free
index 53b49f74da5e31b21cff31a383d6a0ed494fb91d..7cb35790f55c2a258e8ef83940cf123e9d9943e4 100644 (file)
@@ -221,7 +221,6 @@ static void *ParsePcapConfig(const char *iface)
         aconf->snaplen = snaplen;
     }
 
-
     return aconf;
 }
 
index 675747dca7525c1bf16d757d36be51f58dac0967..dba6ba67d959fdb6a9625cc6a6135ea14f994706 100644 (file)
@@ -633,6 +633,9 @@ static void PrintUsage(const char *progname)
 #ifdef WINDIVERT
     printf("\t--windivert <filter>                 : run in inline WinDivert mode\n");
     printf("\t--windivert-forward <filter>         : run in inline WinDivert mode, as a gateway\n");
+#endif
+#ifdef HAVE_LIBNET11
+    printf("\t--reject-dev <dev>                   : send reject packets from this interface\n");
 #endif
     printf("\t--set name=value                     : set a configuration value\n");
     printf("\n");
@@ -1229,6 +1232,9 @@ static TmEcode ParseCommandLine(int argc, char** argv, SCInstance *suri)
 #ifdef WINDIVERT
         {"windivert", required_argument, 0, 0},
         {"windivert-forward", required_argument, 0, 0},
+#endif
+#ifdef HAVE_LIBNET11
+        {"reject-dev", required_argument, 0, 0},
 #endif
         {"set", required_argument, 0, 0},
 #ifdef HAVE_NFLOG
@@ -1524,6 +1530,15 @@ static TmEcode ParseCommandLine(int argc, char** argv, SCInstance *suri)
                 SCLogError(SC_ERR_WINDIVERT_NOSUPPORT,"WinDivert not enabled. Make sure to pass --enable-windivert to configure when building.");
                 return TM_ECODE_FAILED;
 #endif /* WINDIVERT */
+            } else if(strcmp((long_opts[option_index]).name, "reject-dev") == 0) {
+#ifdef HAVE_LIBNET11
+                extern char *g_reject_dev;
+                g_reject_dev = optarg;
+#else
+                SCLogError(SC_ERR_LIBNET_NOT_ENABLED,
+                        "Libnet 1.1 support not enabled. Compile Suricata with libnet support.");
+                return TM_ECODE_FAILED;
+#endif
             }
             else if (strcmp((long_opts[option_index]).name, "set") == 0) {
                 if (optarg != NULL) {