Search code examples
dnswiresharkscapy

rdata field of a DNS-SD PTR packet sent via scapy results in an unknown extended label in wireshark


Currently I'm trying to mock a DNS-SD reply for a query that asked for _printer._tcp.local

What I'm sending with scapy is the following:

send(IP(dst="224.0.0.251")/UDP(sport=5353,dport=5353)/DNS(aa=1, qr=1,rd=0,an=DNSRR(rrname='_printer._tcp.local', type="PTR", rclass=1, ttl=100, rdata="Devon's awesome printer._printer._tcp.local")))

However, when I check in Wireshark I get the following erroneous packet

_printer._tcp.local: type PTR, class IN, <Unknown extended label>

I assume I'm having some wrong parameters in my send function. However, I tried some variations and I can't seem to get it to work properly (I compared with an actual reply from a printer and to me it looks the same).

Could anyone help me out with the correct parameters? Thanks in advance!


Solution

  • This is an outstanding issue as can be seen on scapy's issue tracker.

    Therefore, you have to encode the rdata field yourself, as follows:

    from scapy.all import *
    import struct
    
    label = "Devon's awesome printer._printer._tcp.local"
    sublabels = label.split(".") + [""]
    label_format = ""
    
    for s in sublabels:
        label_format = '%s%dp' % (label_format, len(s) + 1)
        
    label_data = struct.pack(label_format, *sublabels)  # see edit for Python 3 below
    
    send(IP(dst="224.0.0.251")/UDP(sport=5353,dport=5353)/DNS(aa=1,qr=1,rd=0,an=DNSRR(rrname='_printer._tcp.local',type="PTR",rclass=1,ttl=100,rdata=label_data)))
    

    EDIT for Python 3:

    from scapy.all import *
    import struct
    
    label = "Devon's awesome printer._printer._tcp.local"
    sublabels = label.split(".") + [""]
    label_format = ""
    
    for s in sublabels:
        label_format = '%s%dp' % (label_format, len(s) + 1)
        
    label_data = struct.pack(label_format, *(bytes(s, encoding="ascii") for s in sublabels))  # this line was edited for Python 3
    
    send(IP(dst="224.0.0.251")/UDP(sport=5353,dport=5353)/DNS(aa=1,qr=1,rd=0,an=DNSRR(rrname='_printer._tcp.local',type="PTR",rclass=1,ttl=100,rdata=label_data)))