Trying to fetch SRV data with libunbound / libldns

Hello,

I'm trying to use libunbound (and possibly libldns) to pull out SRV
records. I am not certain how to proceed, based on the documentation
that I could found in the form of man pages, tutorials and doxygen.

Am I correct that libunbound returns RDATA unmodified, and is basically
concerned with the security chain but not the RDATA contents? And so,
that I have to turn to another tool?

I therefore looked at LDNS, but that does not seem to help either. I
don't mind following the RFC (though in the case of SRV it is not
explicit on the wire format) to pull out data, but I would be surprised
if I was to make assumptions about the structure of hosts, especially
because it may point back into a DNS packet. Is this really how it is
done though? Then, should I assume the data[i]/len[i] to be pointers
into the frame, and compute offsets manually?

I can hardly believe that this hasn't been tried before :slight_smile: but as I
said, I can't find the documentation that answers this with clarity. So
any help is welcome, including pointers to documentation that I've
overlooked!

Thanks,
-Rick

Rick,

You can parse the packet returned by ub_result.answer_packet with
ldns_wire2pkt(). For example when res is of type ub_result *, then

if ((s = ldns_wire2pkt(&pkt, res->answer_packet, res->answer_len)))
  /* handle error */

else if (!(rrs = ldns_pkt_answer(pkt)))
  /* handle error */

else for (i = 0; i < ldns_rr_list_rr_count(rrs); i++) {
  ldns_rr *rr = ldns_rr_list_rr(rrs, i);

  if (!rr || ldns_rr_get_type(rr) != LDNS_RR_TYPE_SRV)
    continue;

  uint16_t priority = ldns_rdf2native_int16(ldns_rr_rdf(rr, 0));
  uint16_t weight = ldns_rdf2native_int16(ldns_rr_rdf(rr, 1));
  uint16_t port = ldns_rdf2native_int16(ldns_rr_rdf(rr, 2));
  ldns_rdf *target = ldns_rr_rdf(rr, 3);

  /* Do stuff */
}

Not that it is not safe to use ldns_rdf2native_int16 directly on what
ldns_rr_rdf returns. You should test for NULL first. I just wrote it
so for clarity.

Cheers,

-- Willem

Hi Rick,

Hello,

I'm trying to use libunbound (and possibly libldns) to pull out SRV
records. I am not certain how to proceed, based on the documentation
that I could found in the form of man pages, tutorials and doxygen.

Am I correct that libunbound returns RDATA unmodified, and is basically
concerned with the security chain but not the RDATA contents? And so,
that I have to turn to another tool?

I therefore looked at LDNS, but that does not seem to help either. I
don't mind following the RFC (though in the case of SRV it is not
explicit on the wire format) to pull out data, but I would be surprised
if I was to make assumptions about the structure of hosts, especially
because it may point back into a DNS packet. Is this really how it is
done though? Then, should I assume the data[i]/len[i] to be pointers
into the frame, and compute offsets manually?

The data[i] elements contain self-contained, uncompressed, rdata
elements that do not point to a packet somewhere.

For SRV that means there is an uncompressed domainname in there. In
wireformat. LDNS can parse the rdata in data[i].

Best regards, Wouter

The data[i] elements contain self-contained, uncompressed, rdata
elements that do not point to a packet somewhere.

For SRV that means there is an uncompressed domainname in there. In
wireformat. LDNS can parse the rdata in data[i].

Ah yes.. that is much better, so rewriting the example:

char **data;
int *len;

for (data = res->data, len = res->len; *data; data++, len++) {
  if (*len < 7) {
    /* Handle error */
    continue;
  }
  uint16_t priority = ((*data)[0] << 8) | (*data)[1];
  uint16_t weight = ((*data)[2] << 8) | (*data)[3];
  uint16_t port = ((*data)[4] << 8) | (*data)[5];
  ldns_rdf *target_rdf =
      ldns_dname_new_frm_data(*len - 6, *data + 6);
  char *target = ldns_rdf2str(target_rdf);
  ldns_rdf_free(target_rdf);
}

I haven't tested, so there might be errors...

wrapsrv, which is linked from the page below, is an open source tool capable of extracting (and utilizing) SRV records.

https://www.farsightsecurity.com/Blog/20160328-stsauver-magic-of-srv/

vixie

Ah!

Thanks a lot guys! Even with code :slight_smile:

Looks like I was on the right track after all, but struggled to find the vital routines ldns_dname_new_frm_data() and ldns_rdf2str() -- and their pragmatically short names made it difficult for me / newbee to find them. The uncompressed names are vital information too, though!

Cheers,
-Rick