Parse DNS Packet requests and responses

How can I add the header file and use it within a Swift Xcode project?

If you’re building non-library code, you can simply include <dns_util.h> in your bridging header. If you’re building library code, you’ll need to build a wrapper module.

Oh, and the functions are exported by the libresolv.tbd stub library.

Also pardon if I'm misunderstanding, but is there a way to convert a
dns_reply_t object into a character buffer to send out through the
wire?

No. The API is for parsing, not rendering, DNS packets.

As an example, this code:

let packet: [UInt8] = [
    0x21, 0xD9, 0x81, 0x80, 0x00, 0x01, 0x00, 0x01,
    0x00, 0x00, 0x00, 0x01, 0x07, 0x65, 0x78, 0x61,
    0x6D, 0x70, 0x6C, 0x65, 0x03, 0x63, 0x6F, 0x6D,
    0x00, 0x00, 0x01, 0x00, 0x01, 0xC0, 0x0C, 0x00,
    0x01, 0x00, 0x01, 0x00, 0x00, 0xB2, 0x3E, 0x00,
    0x04, 0x5D, 0xB8, 0xD8, 0x22, 0x00, 0x00, 0x29,
    0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
]
let replyQ = packet.withUnsafeBytes { buf -> UnsafeMutablePointer<dns_reply_t>? in
    // Many C APIs, including this one, use `char` values for raw bytes.  On
    // Apple platforms `char` is equivalent to `SInt8`.  However, on the
    // Swift side we typically use `UInt8` for raw bytes and thus so we have
    // to do an ugly cast.
    let base = buf.baseAddress!.assumingMemoryBound(to: Int8.self)
    return dns_parse_packet(base, UInt32(buf.count))
}
guard let reply = replyQ else { fatalError() }
// The 0xffff should be a combinary of `DNS_PRINT_` flags but there’s no
// ‘all’ flag so I’m taking a shortcut.
dns_print_reply(reply, stdout, 0xffff)

prints this:

Xid: 8665
QR: Reply
Server: -nil-
Opcode: Standard
AA: Non-Authoritative
TC: Non-Truncated
RD: Recursion desired
RA: Recursion available
Rcode: No error
Question (1):
example.com IN A    
Answer (1):
example.com IN A     45630 93.184.216.34
Authority (0):
Additional records (1):
 ?? OPT   0 0  ()

Share and Enjoy

Quinn “The Eskimo!” @ DTS @ Apple

2 Likes