Since Deadwood is currently a non-recursive cache, we have only one task we perform: We send a DNS query to an upstream server, whose reply we cache and forward on to the end-user.
Since Deadwood only does one task,
the structure for remote connections doesn’t need to store what task we’re doing with a remote connection.
This needs to be changed to implement full recursion.
So, let’s add to that structure a “task” element: What we’re doing right now in our process of solving a recursive DNS query.
We can have Deadwood perform the following tasks:
- We are connecting to an upstream DNS server with the RD (recursion desired) bit set. Whatever reply they give us is one we will cache and forward on to the stub resolver. This is currently the only task Deadwood can do. Should the connection fail, or the reply is not a “complete” DNS reply, we will try another upstream server.
- We are connecting to a DNS server which is marked as being a possible NS server to our query. The reply is one we may or may not pass on to the client, depending on whether it is a complete reply.
- We got an incomplete CNAME referral, which indicates we need to change the name of our query to whatever name was at the end of the incomplete referral and do a new query
Tasks will be stored as a stack. The first taks we will have is to connect to the “lowest” NS server we have an entry for. Here is how our remote query will look:
Main -> Non-recursive NS server connect (solve client query).
Should we need to resolve the IP for a glueless NS server, here is how the above task list will then look like this:
Main -> Non-recursive NS server connect (solve glueless IP) -> Non-recursive NS server connect.
If, when trying to solve the glueless IP, we need to solve an incomplete CNAME referral:
Main -> Non-recursive NS server connect (solve incomplete CNAME referral) -> Non-recursive NS server connect (solve glueless IP) -> Non-recursive NS server connect (solve client query)
OK, looking at this, our task will
always be trying to make a non-recursive NS server connection. However, we need to store why we’re making this query (client query, glueless IP, or incomplete CNAME referral).
So, we’ll keep the SOCKET, remote_id and the time-to-die, as well as a pointer to the local queries for this query and the initial local query in the “root node”. However, the number of retries as well as the query we’re doing to store this particular task, as well as the list of NS servers we will try to connect, and the number of times we will try before giving up, need to be stored in a special “task” structure which will be stored as a stack pointed to by the “root” DNS query.