aboutgitcodebugslistschat
path: root/tap.c
diff options
context:
space:
mode:
Diffstat (limited to 'tap.c')
-rw-r--r--tap.c31
1 files changed, 31 insertions, 0 deletions
diff --git a/tap.c b/tap.c
index e323529..a6a73d3 100644
--- a/tap.c
+++ b/tap.c
@@ -62,6 +62,7 @@ static PACKET_POOL_NOINIT(pool_tap4, TAP_MSGS, pkt_buf);
static PACKET_POOL_NOINIT(pool_tap6, TAP_MSGS, pkt_buf);
#define TAP_SEQS 128 /* Different L4 tuples in one batch */
+#define FRAGMENT_MSG_RATE 10 /* # seconds between fragment warnings */
/**
* tap_send() - Send frame, with qemu socket header if needed
@@ -544,6 +545,32 @@ static void tap_packet_debug(const struct iphdr *iph,
}
/**
+ * tap4_is_fragment() - Determine if a packet is an IP fragment
+ * @iph: IPv4 header (length already validated)
+ * @now: Current timestamp
+ *
+ * Return: true if iph is an IP fragment, false otherwise
+ */
+static bool tap4_is_fragment(const struct iphdr *iph,
+ const struct timespec *now)
+{
+ if (ntohs(iph->frag_off) & ~IP_DF) {
+ /* Ratelimit messages */
+ static time_t last_message;
+ static unsigned num_dropped;
+
+ num_dropped++;
+ if (now->tv_sec - last_message > FRAGMENT_MSG_RATE) {
+ warn("Can't process IPv4 fragments (%lu dropped)", num_dropped);
+ last_message = now->tv_sec;
+ num_dropped = 0;
+ }
+ return true;
+ }
+ return false;
+}
+
+/**
* tap4_handler() - IPv4 and ARP packet handler for tap file descriptor
* @c: Execution context
* @in: Ingress packet pool, packets with Ethernet headers
@@ -591,6 +618,10 @@ resume:
hlen > l3_len)
continue;
+ /* We don't handle IP fragments, drop them */
+ if (tap4_is_fragment(iph, now))
+ continue;
+
l4_len = l3_len - hlen;
if (iph->saddr && c->ip4.addr_seen.s_addr != iph->saddr) {