There is “Postel's Law” in protocol design that states:
2.10. Robustness Principle
TCP implementations will follow a general principle of robustness: be conservative in what you do, be liberal in what you accept from others.
But then there's this:
A well-designed protocol is robust.
Robustness and efficiency are often at odds. For example, although defaults are useful to reduce packet sizes and processing time, they tend to encourage implementation errors.
Counter-intuitively, Postel's robustness principle ("be conservative in what you send, liberal in what you accept") often leads to deployment problems. Why? When a new implementation is initially fielded, it is likely that it will encounter only a subset of existing implementations. If those implementations follow the robustness principle, then errors in the new implementation will likely go undetected. The new implementation then sees some, but not widespread deployment. This process repeats for several new implementations. Eventually, the not-quite-correct implementations run into other implementations that are less liberal than the initial set of implementations. The reader should be able to figure out what happens next.
Accordingly, explicit consistency checks in a protocol are very useful, even if they impose implementation overhead.
I bring this up because I recently came across this:
… The first byte of the clear data was a flags field which, he said, was promptly ossified by a middlebox vendor, leading to packets being dropped when a new flag was set.
That was a classic example of why changing network protocols is hard and what needs to be done to improve the situation. Middleboxes are the control points for the Internet as we know it now. The only defense against ossification of network protocols by middleboxes, he said at the conclusion of the talk, is encryption.
And I thought, Oh crap! I do that!
Am I ossifying the DNS protocol by doing this?
I did encounter this a few months ago.
I was playing around with monitoring the traffic on the home network and saw a bunch of MDNS
requests flying around.
I thought I would decode them using
SPCDNS to see what exactly was being queried when I hit a snag—some of the packets were invalid!
it came down to that single undefined bit in the DNS packet being set.
I quickly patched the code (privately) to accept the packets but I didn't release the changes since at the time,
that last undefined bit was still undefined.
I didn't know how to deal with the situation then,
and I still don't.
SPCDNS can handle records it doesn't understand, but that one undefined bit has me stymied.
I could define the flag and let a user of my code check for it,
but when it does become defined,
that flag name will obviously have to change and that could be a breaking change.
But as of right now,
any user code that wants to check for that bit has no way of doing so
(not that I've received any requests for it).
Then there's the fact that because my code was so fussy with verifying the packet, that bugs in other DNS implementations were found via my code. And at work, I put up a fight to remain picky in processing network packets for “Project: Sippy-Cup.” I mean, what's the point of a protocol specification if you don't follow it? I even referenced RFC-3177 (quoted above) as part of my argument for being picky. But I was overridden and had to carry on in the face of utter garbage (and yes, some of what we get is utter garbage). I did however keep track of each violation and we are in the process of talking with a vendor who is sending us garbage as I type.
This is tough.
At the time I wrote
SPCDNS, there was only one undefined bit left in the DNS packet.
Had I written it back when RFC-1035 was written,
there would have been three undefined bits,
and I ask myself how I would have handled that over the years.
I'm not even sure if I would have thought to include those bits in what is decoded
(I don't now).
This will require some thought.