Skip to content

Commit

Permalink
Merge "Add support for SRV DNS record type." into R3.0
Browse files Browse the repository at this point in the history
  • Loading branch information
Zuul authored and opencontrail-ci-admin committed May 20, 2016
2 parents c2e84d8 + 6cf8c3e commit d75311a
Show file tree
Hide file tree
Showing 3 changed files with 81 additions and 0 deletions.
24 changes: 24 additions & 0 deletions src/dns/bind/bind_util.cc
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ DnsTypeMap g_dns_type_map = map_list_of<std::string, uint16_t>
("MX", 0x0F)
("TXT", 0x10)
("AAAA", 0x1C)
("SRV", 0x21)
("ANY", 0xFF);

DnsTypeNumMap g_dns_type_num_map = map_list_of<uint16_t, std::string>
Expand All @@ -28,6 +29,7 @@ DnsTypeNumMap g_dns_type_num_map = map_list_of<uint16_t, std::string>
(DNS_MX_RECORD, "MX")
(DNS_TXT_RECORD, "TXT")
(DNS_AAAA_RECORD, "AAAA")
(DNS_SRV_RECORD, "SRV")
(DNS_TYPE_ANY, "ANY");

DnsTypeNumMap g_dns_class_num_map = map_list_of<uint16_t, std::string>
Expand Down Expand Up @@ -192,6 +194,19 @@ uint8_t *BindUtil::AddData(uint8_t *ptr, const DnsItem &item,
ptr = WriteShort(ptr, item.priority);
ptr = AddName(ptr, item.data, item.data_plen, item.data_offset, length);
length += 2 + 2;
} else if (item.type == DNS_SRV_RECORD) {
uint16_t data_len = 6 + DataLength(item.srv.hn_plen, item.srv.hn_offset,
item.srv.hostname.size());
ptr = WriteShort(ptr, data_len);
ptr = WriteShort(ptr, item.srv.priority);
ptr = WriteShort(ptr, item.srv.weight);
ptr = WriteShort(ptr, item.srv.port);
ptr = AddName(ptr, item.srv.hostname, item.srv.hn_plen,
item.srv.hn_offset, length);
length += 2 + 6;
} else {
DNS_BIND_TRACE(DnsBindError,
"Unsupported record type in response : " << item.type);
}

return ptr;
Expand Down Expand Up @@ -319,6 +334,15 @@ bool BindUtil::ReadData(uint8_t *dns, uint16_t dnslen, int *remlen,
if (ReadShort(dns, dnslen, remlen, item.priority) == false)
return false;
return ReadName(dns, dnslen, remlen, item.data, item.data_plen, item.data_offset);
} else if (item.type == DNS_SRV_RECORD) {
if (ReadShort(dns, dnslen, remlen, item.srv.priority) == false)
return false;
if (ReadShort(dns, dnslen, remlen, item.srv.weight) == false)
return false;
if (ReadShort(dns, dnslen, remlen, item.srv.port) == false)
return false;
return ReadName(dns, dnslen, remlen, item.srv.hostname,
item.srv.hn_plen, item.srv.hn_offset);
}

DNS_BIND_TRACE(DnsBindError,
Expand Down
14 changes: 14 additions & 0 deletions src/dns/bind/bind_util.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ do { \
#define DNS_MX_RECORD 0x0F
#define DNS_TXT_RECORD 0x10
#define DNS_AAAA_RECORD 0x1C
#define DNS_SRV_RECORD 0x21
#define DNS_TYPE_ANY 0x00ff

// DNS return codes
Expand Down Expand Up @@ -131,6 +132,18 @@ struct DnsSOAData {
}
};

// Data format in an SRV record
struct DnsSRVData {
uint16_t priority;
uint16_t weight;
uint16_t port;
std::string hostname;
uint16_t hn_plen; // length of the prefix in hostname that is unique
uint16_t hn_offset; // offset from where rest of hostname name exists

DnsSRVData() : hn_plen(0), hn_offset(0) {}
};

struct DnsItem {
uint16_t eclass;
uint16_t type;
Expand All @@ -144,6 +157,7 @@ struct DnsItem {
std::string name;
std::string data;
DnsSOAData soa;
DnsSRVData srv;

DnsItem() : eclass(1), type(0), ttl(0), priority(0), offset(0),
name_plen(0), name_offset(0), data_plen(0), data_offset(0), soa() {}
Expand Down
43 changes: 43 additions & 0 deletions src/dns/test/dns_bind_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1057,6 +1057,49 @@ TEST_F(DnsBindTest, DnsUpdateErrorParse) {
EXPECT_FALSE(BindUtil::ParseDnsUpdate(buf, len, data));
}

// Check the parsing of a DNS SRV Response
TEST_F(DnsBindTest, DnsResponseSRVParse) {
uint8_t buf[1024];
int count = 1;
DnsItems ans_in, auth_in, add_in;

DnsItem item;
item.eclass = DNS_CLASS_IN;
item.type = DNS_SRV_RECORD;
item.ttl = 100;
item.name = "_rubygems._tcp.rubygems.org";
item.srv.priority = 0;
item.srv.weight = 1;
item.srv.port = 80;
item.srv.hostname = "api.rubygems.org";
ans_in.push_back(item);

dnshdr *dns = (dnshdr *) buf;
BindUtil::BuildDnsHeader(dns, 0x0102, DNS_QUERY_RESPONSE, DNS_OPCODE_QUERY,
0, 0, 0, 0);
dns->ques_rrcount = htons(count);
dns->ans_rrcount = htons(count);
dns->auth_rrcount = 0;
dns->add_rrcount = 0;

uint16_t len = sizeof(dnshdr);
uint8_t *ptr = (uint8_t *) (dns + 1);
for (int i = 0; i < count; i++)
ptr = BindUtil::AddQuestionSection(ptr, "_rubygems._tcp.rubygems.org",
DNS_SRV_RECORD, DNS_CLASS_IN, len);
for (DnsItems::iterator it = ans_in.begin(); it != ans_in.end(); it++)
ptr = BindUtil::AddAnswerSection(ptr, *it, len);

uint16_t xid;
dns_flags flags;
DnsItems ques, ans, auth, add;
EXPECT_TRUE(BindUtil::ParseDnsResponse(buf, len, xid, flags,
ques, ans, auth, add));
EXPECT_TRUE(ans == ans_in);
}



} // namespace

int main(int argc, char **argv) {
Expand Down

0 comments on commit d75311a

Please sign in to comment.