Subject: Handling of unexpectedly large UDP packets

Handling of unexpectedly large UDP packets

From: Ben Nason via c-ares <>
Date: Thu, 27 Oct 2016 13:35:22 -0700


I noticed recently this bit of code in ares_process.c, process_answer():

  /* If we got a truncated UDP packet and are not ignoring truncation,
   * don't accept the packet, and switch the query to TCP if we hadn't
   * done so already.
  if ((tc || alen > packetsz) && !tcp && !(channel->flags &
      if (!query->using_tcp)
          query->using_tcp = 1;
          ares__send_query(channel, query, now);

  /* Limit alen to PACKETSZ if we aren't using TCP (only relevant if we
   * are ignoring truncation.
  if (alen > packetsz && !tcp)
      alen = packetsz;

I'm wondering about the two "alen > packetsz" checks. I've seen some
servers send larger than 512 byte UDP responses even without EDNS enabled.
In this case the server is being a bad citizen and sending a response that
is invalid, strictly speaking. However, arguably the response data itself
is perfectly fine when this happens, and c-ares is either retrying with TCP
or truncating manually. Are there other cases where this happens when it is
actually problematic so c-ares needs to be strict like this? Or maybe it's
a judgement call and c-ares just wants to be strict to maintain the most
proper behavior? Or am I just misunderstanding something?

You can see an example of a server that does this: "dig @ AAAA
+notcp +ignore +noedns"

Received on 2016-10-27