如何用ldns库解析unbound返回的ub_result中data字段为TLSA记录?
将Unbound的ub_result中data字段解析为TLSA记录(ldns库实现)
Unbound DNS解析器返回的ub_result结构定义如下:
struct ub_result { char* qname; /* text string, original question */ int qtype; /* type code asked for */ int qclass; /* class code asked for */ char** data; /* array of rdata items, NULL terminated*/ int* len; /* array with lengths of rdata items */ char* canonname; /* canonical name of result */ int rcode; /* additional error code in case of no data */ void* answer_packet; /* full network format answer packet */ int answer_len; /* length of packet in octets */ int havedata; /* true if there is data */ int nxdomain; /* true if nodata because name does not exist */ int secure; /* true if result is secure */ int bogus; /* true if a security failure happened */ char* why_bogus; /* string with error if bogus */ };
问题
需要使用ldns库解析上述结构中的data字段,将其转换为已解析的TLSA记录。ldns文档仅描述了从零创建TLSA记录的方法,缺少反向解析的相关说明。
解决方案
ub_result->data中的每个元素是TLSA记录的原始二进制RData(网络字节序),需通过以下ldns API步骤解析:
1. 将二进制数据转为ldns_rdf对象
ldns_rdf是ldns中表示资源数据的基础结构,使用ldns_rdf_new_frm_data()将data字段的二进制内容包装成对应类型的RDF:
// 遍历data数组(NULL终止),i为当前索引 ldns_rdf *tlsa_rdf = ldns_rdf_new_frm_data( LDNS_RDF_TYPE_TLSA, ub_result->len[i], (uint8_t*)ub_result->data[i] );
2. 将ldns_rdf包装为完整的TLSA资源记录(ldns_rr)
TLSA是完整的DNS资源记录,需把RDF包装成ldns_rr对象,可直接使用ldns_rr_new_frm_rdf():
ldns_rr *tlsa_rr = ldns_rr_new_frm_rdf( LDNS_RR_TYPE_TLSA, ub_result->qclass, // 使用Unbound返回的类,通常为IN类(LDNS_RR_CLASS_IN) tlsa_rdf );
注:通过
ldns_rr_new_frm_rdf()创建的ldns_rr会自动管理tlsa_rdf的内存,无需单独释放tlsa_rdf。
3. 提取TLSA记录的各个字段
使用ldns提供的TLSA专用访问函数,可直接获取解析后的各个字段:
- 证书使用字段:
uint8_t cert_usage = ldns_rr_tlsa_cert_usage(tlsa_rr); - 选择器字段:
uint8_t selector = ldns_rr_tlsa_selector(tlsa_rr); - 匹配类型字段:
uint8_t matching_type = ldns_rr_tlsa_matching_type(tlsa_rr); - 证书关联数据:
ldns_rdf *assoc_data = ldns_rr_tlsa_association_data(tlsa_rr);
可通过ldns_rdf_data(assoc_data)获取二进制数据指针,ldns_rdf_size(assoc_data)获取数据长度。
4. 内存清理
使用完资源后释放ldns_rr对象:
ldns_rr_free(tlsa_rr);
注意事项
- 处理前需检查
ub_result->havedata为真,且ub_result->qtype等于LDNS_RR_TYPE_TLSA(数值为52),避免处理非TLSA数据。 ub_result->data是NULL终止的数组,需循环遍历直到遇到NULL元素。
内容的提问来源于stack exchange,提问作者Graham Leggett
相关产品推荐
相关产品推荐

