scapy icon indicating copy to clipboard operation
scapy copied to clipboard

RFE: mDNS unicast-response and cache-flush bits

Open evverx opened this issue 9 months ago • 2 comments

Brief description

Currently the unicast-response and cache-flush bits aren't supported.

(It's mostly cosmetic because it's possible to get/set those bits manually. It's just something I noticed when I started playing with https://github.com/secdev/scapy/pull/4385)

Scapy version

f17e8da65d9299d6dbc84b427aaf7761aff31355

Python version

3.12.3

Operating system

6.8.9-300.fc40.x86_64

Additional environment information

No response

How to reproduce

with_unicast_response_bit = DNS(b'\x00\x00\x00\x00\x00\x02\x00\x00\x00\x03\x00\x00\x01Q\x05_qotd\x04_tcp\x05local\x00\x00\xff\x80\x01\x06host-5\x05local\x00\x00\xff\x80\x01\x01Q\x05_qotd\x04_tcp\x05local\x00\x00!\x00\x01\x00\x00\x00x\x00\x14\x00\x00\x00\x00\x00{\x06host-5\x05local\x00\x06host-5\x05local\x00\x00\x01\x00\x01\x00\x00\x00x\x00\x04\xc0\xa88\x03\x06host-5\x05local\x00\x00\x1c\x00\x01\x00\x00\x00x\x00\x10\xfe\x80\x00\x00\x00\x00\x00\x00\x1c\x12+\xc1\xf3]\x97\x94')
with_cache_flush_bit = DNS(b'\x00\x00\x84\x00\x00\x00\x00\x06\x00\x00\x00\x02\x01Q\x05_qotd\x04_tcp\x05local\x00\x00\x10\x80\x01\x00\x00\x11\x94\x00\x01\x00\t_services\x07_dns-sd\x04_udp\x05local\x00\x00\x0c\x00\x01\x00\x00\x11\x94\x00\x12\x05_qotd\x04_tcp\x05local\x00\x05_qotd\x04_tcp\x05local\x00\x00\x0c\x00\x01\x00\x00\x11\x94\x00\x14\x01Q\x05_qotd\x04_tcp\x05local\x00\x01Q\x05_qotd\x04_tcp\x05local\x00\x00!\x80\x01\x00\x00\x00x\x00\x14\x00\x00\x00\x00\x00{\x06host-5\x05local\x00\x06host-5\x05local\x00\x00\x01\x80\x01\x00\x00\x00x\x00\x04\xc0\xa88\x03\x06host-5\x05local\x00\x00\x1c\x80\x01\x00\x00\x00x\x00\x10\xfe\x80\x00\x00\x00\x00\x00\x00\x1c\x12+\xc1\xf3]\x97\x94\x01Q\x05_qotd\x04_tcp\x05local\x00\x00/\x80\x01\x00\x00\x11\x94\x00\x1b\x01Q\x05_qotd\x04_tcp\x05local\x00\x00\x05\x00\x00\x80\x00@\x06host-5\x05local\x00\x00/\x80\x01\x00\x00\x00x\x00\x14\x06host-5\x05local\x00\x00\x04@\x00\x00\x08')

Actual result

>>> with_unicast_response_bit.qd[0].show()
###[ DNS Question Record ]###
  qname     = b'Q._qotd._tcp.local.'
  qtype     = ALL
  qclass    = 32769
>>> with_cache_flush_bit.an[0].show()
###[ DNS Resource Record ]###
  rrname    = b'Q._qotd._tcp.local.'
  type      = TXT
  rclass    = 32769
  ttl       = 4500
  rdlen     = None
  rdata     = [b'']

Expected result

tshark shows

        Q._qotd._tcp.local: type ANY, class IN, "QU" question
            Name: Q._qotd._tcp.local
            [Name Length: 18]
            [Label Count: 4]
            Type: ANY (255) (A request for all records the server/cache has available)
            .000 0000 0000 0001 = Class: IN (0x0001)
            1... .... .... .... = "QU" question: True

and

        Q._qotd._tcp.local: type TXT, class IN, cache flush
            Name: Q._qotd._tcp.local
            Type: TXT (16) (Text strings)
            .000 0000 0000 0001 = Class: IN (0x0001)
            1... .... .... .... = Cache flush: True
            Time to live: 4500 (1 hour, 15 minutes)
            Data length: 1
            TXT Length: 0
            TXT: 

respectively.

Related resources

https://datatracker.ietf.org/doc/html/rfc6762#section-19

Multicast DNS... ...

  • defines a unicast-response bit in the rrclass of query questions
  • defines a cache-flush bit in the rrclass of response records

https://datatracker.ietf.org/doc/html/rfc6762#section-5.4

Multicast DNS defines the top bit in the class field of a DNS question as the unicast-response bit. When this bit is set in a question, it indicates that the querier is willing to accept unicast replies in response to this specific query, as well as the usual multicast responses. These questions requesting unicast responses are referred to as "QU" questions, to distinguish them from the more usual questions requesting multicast responses ("QM" questions).

https://datatracker.ietf.org/doc/html/rfc6762#section-10.2

the host MUST then send a series of unsolicited announcements to update cache entries in its neighbor hosts. In these unsolicited announcements, if the record is one that has been verified unique, the host sets the most significant bit of the rrclass field of the resource record. This bit, the cache-flush bit, tells neighboring hosts that this is not a shared record type.

evverx avatar May 13 '24 02:05 evverx

That's a good point. It's pretty similar to LLMNR.

I'll add it to #4385 when I get the time. Edit: I ended up merging it but I'll make it into a future PR.

gpotter2 avatar May 13 '24 06:05 gpotter2

You can checkout https://github.com/secdev/scapy/pull/4390

I just added the bits everywhere. It might be an annoyance for classes > 32k for classic DNS.. but I'm unsure those are frequent so it'll do for now.

gpotter2 avatar May 15 '24 00:05 gpotter2