]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
reject: get MTU for reject-dev and use it
authorVictor Julien <victor@inliniac.net>
Fri, 12 Jun 2020 13:52:00 +0000 (15:52 +0200)
committerVictor Julien <victor@inliniac.net>
Sun, 28 Jun 2020 13:20:56 +0000 (15:20 +0200)
src/respond-reject-libnet11.c
src/suricata.c

index fe7e7bdf43ce948a320797c8567847fab87b29f3..245b7a397ec1f53e01579d09dc2c93cd84813789 100644 (file)
@@ -59,6 +59,7 @@
 
 /* Globally configured device to use for sending resets in IDS mode. */
 const char *g_reject_dev = NULL;
+uint16_t g_reject_dev_mtu = 0;
 
 /** 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. */
@@ -193,10 +194,8 @@ static inline int BuildTCP(libnet_t *c, Libnet11Packet *lpacket)
 
 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(
-                    len,                          /* entire packet length */
+                    lpacket->len,                 /* entire packet length */
                     0,                            /* tos */
                     lpacket->id,                  /* ID */
                     0,                            /* fragmentation flags and offset */
@@ -218,12 +217,10 @@ static inline int BuildIPv4(libnet_t *c, Libnet11Packet *lpacket, const uint8_t
 
 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 */
+                    lpacket->len,                 /* payload length */
                     proto,                        /* next header */
                     lpacket->ttl,                 /* TTL */
                     lpacket->src6,                /* source address */
@@ -254,6 +251,7 @@ static inline void SetupEthernet(Packet *p, Libnet11Packet *lpacket, int dir)
             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) {
@@ -281,7 +279,7 @@ int RejectSendLibnet11IPv4TCP(ThreadVars *tv, Packet *p, void *data, int dir)
     if (c == NULL)
         return 1;
 
-    /* save payload len */
+    lpacket.len = LIBNET_IPV4_H + LIBNET_TCP_H;
     lpacket.dsize = p->payload_len;
 
     switch (dir) {
@@ -332,7 +330,13 @@ int RejectSendLibnet11IPv4ICMP(ThreadVars *tv, Packet *p, void *data, int dir)
     lpacket.id = 0;
     lpacket.flow = 0;
     lpacket.class = 0;
-    lpacket.len = (IPV4_GET_HLEN(p) + p->payload_len);
+    const int iplen = IPV4_GET_IPLEN(p);
+    if (g_reject_dev_mtu >= ETHERNET_HEADER_LEN + LIBNET_IPV4_H + 8) {
+        lpacket.len = MIN(g_reject_dev_mtu - ETHERNET_HEADER_LEN, (LIBNET_IPV4_H + iplen));
+    } else {
+        lpacket.len = LIBNET_IPV4_H + MIN(8,iplen); // 8 bytes is the minimum we have to attach
+    }
+    lpacket.dsize = lpacket.len - (LIBNET_IPV4_H + LIBNET_ICMPV4_H);
 
     libnet_t *c = GetCtx(p, LIBNET_RAW4);
     if (c == NULL)
@@ -362,7 +366,7 @@ int RejectSendLibnet11IPv4ICMP(ThreadVars *tv, Packet *p, void *data, int dir)
                     ICMP_HOST_ANO,            /* code */
                     0,                        /* checksum */
                     (uint8_t *)p->ip4h,       /* payload */
-                    lpacket.len,              /* payload length */
+                    lpacket.dsize,            /* payload length */
                     c,                        /* libnet context */
                     0)) < 0)                  /* libnet ptag */
     {
@@ -408,7 +412,7 @@ int RejectSendLibnet11IPv6TCP(ThreadVars *tv, Packet *p, void *data, int dir)
     if (c == NULL)
         return 1;
 
-    /* save payload len */
+    lpacket.len = LIBNET_IPV6_H + LIBNET_TCP_H;
     lpacket.dsize = p->payload_len;
 
     switch (dir) {
@@ -459,7 +463,13 @@ int RejectSendLibnet11IPv6ICMP(ThreadVars *tv, Packet *p, void *data, int dir)
     lpacket.id = 0;
     lpacket.flow = 0;
     lpacket.class = 0;
-    lpacket.len = IPV6_GET_PLEN(p) + IPV6_HEADER_LEN;
+    const int iplen = IPV6_GET_PLEN(p);
+    if (g_reject_dev_mtu >= ETHERNET_HEADER_LEN + IPV6_HEADER_LEN + 8) {
+        lpacket.len = IPV6_HEADER_LEN + MIN(g_reject_dev_mtu - ETHERNET_HEADER_LEN, iplen);
+    } else {
+        lpacket.len = IPV6_HEADER_LEN + MIN(8, iplen);
+    }
+    lpacket.dsize = lpacket.len - LIBNET_ICMPV6_H;
 
     libnet_t *c = GetCtx(p, LIBNET_RAW6);
     if (c == NULL)
@@ -489,7 +499,7 @@ int RejectSendLibnet11IPv6ICMP(ThreadVars *tv, Packet *p, void *data, int dir)
                     ICMP6_DST_UNREACH_ADMIN,  /* code */
                     0,                        /* checksum */
                     (uint8_t *)p->ip6h,       /* payload */
-                    lpacket.len,              /* payload length */
+                    lpacket.dsize,            /* payload length */
                     c,                        /* libnet context */
                     0)) < 0)                  /* libnet ptag */
     {
@@ -497,7 +507,7 @@ int RejectSendLibnet11IPv6ICMP(ThreadVars *tv, Packet *p, void *data, int dir)
         goto cleanup;
     }
 
-    if (BuildIPv6(c, &lpacket, IPPROTO_ICMP) < 0)
+    if (BuildIPv6(c, &lpacket, IPPROTO_ICMPV6) < 0)
         goto cleanup;
 
     if (t_inject_mode == LIBNET_LINK) {
index dba6ba67d959fdb6a9625cc6a6135ea14f994706..b58e3dab673034442cf6e9d024d4a6f3f5aa4d99 100644 (file)
@@ -1533,7 +1533,12 @@ static TmEcode ParseCommandLine(int argc, char** argv, SCInstance *suri)
             } else if(strcmp((long_opts[option_index]).name, "reject-dev") == 0) {
 #ifdef HAVE_LIBNET11
                 extern char *g_reject_dev;
+                extern uint16_t g_reject_dev_mtu;
                 g_reject_dev = optarg;
+                int mtu = GetIfaceMTU(g_reject_dev);
+                if (mtu > 0) {
+                    g_reject_dev_mtu = (uint16_t)mtu;
+                }
 #else
                 SCLogError(SC_ERR_LIBNET_NOT_ENABLED,
                         "Libnet 1.1 support not enabled. Compile Suricata with libnet support.");